Я хочу создать подкласс IntEnum с именем MqHandShakeE в C, используя Tcl-C-код из примера в качестве шаблона
int NS(Get_MqHandShakeE_FromObj) (Tcl_Interp *interp, Tcl_Obj *enumE, enum MqHandShakeE *ret) {
int index;
const static struct LookupEnumE keys[] = {
{ "START", MQ_HANDSHAKE_START },
{ "OK", MQ_HANDSHAKE_OK },
{ "ERROR", MQ_HANDSHAKE_ERROR },
{ NULL, 0 }
};
TclErrorCheck (Tcl_GetIndexFromObjStruct (interp, enumE, &keys,
sizeof(struct LookupClassS), "enum", TCL_EXACT, &index));
*ret = keys[index].val;
return TCL_OK;
}
Моя цель - вызвать функцию Python с помощью…
myfunc … MqHandShakeE.OK …
C-константа MQ_HANDSHAKE_START - это ЦЕЛОЕ
Единственное решение Python:
from enum import IntEnum
class WAIT(IntEnum):
NO = 0
ONCE = 1
FOREVER = 2
это типобезопасно, потому что WAIT.NO имеет тип WAIT и значение 0… это я могу проверить… подход субмодуля снизу безопасен по типу нет… WAIT.NO как субмодуль имеет тип int
Я тестирую подход субмодуль ... проблема в том ... что это типичный НЕТ






После того, как я опубликовал образец для C++, я понял, что OP пометил вопрос с помощью C (а не C++). Извини, это моя вина. Вот образец на C:
#include <Python.h>
#include <assert.h>
#include <stdio.h>
/* sample enum in C */
enum MQ_HANDSHAKE {
MQ_HANDSHAKE_START,
MQ_HANDSHAKE_OK,
MQ_HANDSHAKE_ERROR
};
/* make Python binding for MQ_HANDSHAKE */
static struct PyModuleDef moduleMQ_HANDSHAKE = {
PyModuleDef_HEAD_INIT,
"MQ_HANDSHAKE", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
* or -1 if the module keeps state in global variables.
*/
NULL /* function table (no functions) */
};
static PyObject* initModuleMQ_HANDSHAKE(void)
{
static PyObject *pSelf = NULL;
if (!pSelf) {
pSelf = PyModule_Create(&moduleMQ_HANDSHAKE);
PyModule_AddObject(pSelf, "START", PyLong_FromLong(MQ_HANDSHAKE_START));
PyModule_AddObject(pSelf, "OK", PyLong_FromLong(MQ_HANDSHAKE_OK));
PyModule_AddObject(pSelf, "ERROR", PyLong_FromLong(MQ_HANDSHAKE_ERROR));
}
return pSelf;
}
/* adds module MQ_HANDSHAKE to Python modules table.
*/
void appendModuleMQ_HANDSHAKE(void)
{
assert(!Py_IsInitialized());
PyImport_AppendInittab("MQ_HANDSHAKE", &initModuleMQ_HANDSHAKE);
}
/* test program */
int main()
{
/* initialize Python extension MQ_HANDSHAKE */
appendModuleMQ_HANDSHAKE();
/* initialize Python interpreter */
Py_Initialize();
/* sample Python program */
static const char *const pyProgram
= "print(\"Hello world (from Python).\")\n"
"\n"
"# import Python extension MQ_HANDSHAKE\n"
"import MQ_HANDSHAKE\n"
"\n"
"# test whether it works\n"
"def printHandshake(value):\n"
" if value == MQ_HANDSHAKE.START:\n"
" print(\"MQ_HANDSHAKE_START\")\n"
" elif value == MQ_HANDSHAKE.OK:\n"
" print(\"MQ_HANDSHAKE_OK\")\n"
" elif value == MQ_HANDSHAKE.ERROR:\n"
" print(\"MQ_HANDSHAKE_ERROR\")\n"
" else:\n"
" print(\"Illegal MQ_HANDSHAKE value!\")\n"
"\n"
"printHandshake(MQ_HANDSHAKE.START)\n"
"printHandshake(MQ_HANDSHAKE.OK)\n"
"printHandshake(MQ_HANDSHAKE.ERROR)\n"
"printHandshake(0)\n"
"printHandshake(1)\n"
"printHandshake(2)\n"
"printHandshake(42)\n";
/* run Python interpreter */
const int ret = PyRun_SimpleString(pyProgram);
if (ret) {
fprintf(stderr, "Execution in PyRun_SimpleString() failed!\n");
}
/* done */
return ret;
}
Скомпилировано и протестировано в VS2013 с Python 3.6:
Hello world (from Python).
MQ_HANDSHAKE_START
MQ_HANDSHAKE_OK
MQ_HANDSHAKE_ERROR
MQ_HANDSHAKE_START
MQ_HANDSHAKE_OK
MQ_HANDSHAKE_ERROR
Illegal MQ_HANDSHAKE value!
В этом образце установлен модуль MQ_HANDSHAKE, который
- должен быть добавлен в таблицы Python (с использованием PyImport_AppendInittab())
до того, как был вызван PyInitialize()
- должен быть импортирован в код Python (с использованием import MQ_HANDSHAKE).
Исходный ответ с кодом на C++:
Я взглянул на наши оболочки Python и сделал небольшой образец для случая OP:
#include <Python.h>
#include <cassert>
#include <iostream>
// sample enum in C/C++
enum MQ_HANDSHAKE {
MQ_HANDSHAKE_START,
MQ_HANDSHAKE_OK,
MQ_HANDSHAKE_ERROR
};
namespace Py {
namespace MQ {
// make Python binding for MQ_HANDSHAKE
namespace HANDSHAKE {
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"mq.Handshake", // name of module
nullptr, // module documentation, may be NULL
-1, /* size of per-interpreter state of the module,
* or -1 if the module keeps state in global variables.
*/
nullptr // function table (no functions)
};
static PyObject* init()
{
static PyObject *pSelf = nullptr;
if (!pSelf) {
pSelf = PyModule_Create(&module);
PyModule_AddObject(pSelf, "START", PyLong_FromLong(MQ_HANDSHAKE_START));
PyModule_AddObject(pSelf, "OK", PyLong_FromLong(MQ_HANDSHAKE_OK));
PyModule_AddObject(pSelf, "ERROR", PyLong_FromLong(MQ_HANDSHAKE_ERROR));
}
return pSelf;
}
} // namespace HANDSHAKE
// make module MQ
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"mq", // name of module
nullptr, // module documentation, may be NULL
-1, /* size of per-interpreter state of the module,
* or -1 if the module keeps state in global variables.
*/
nullptr // function table (no functions)
};
// initializes module mq
static PyObject* init()
{
static PyObject *pSelf = nullptr;
if (!pSelf) {
pSelf = PyModule_Create(&module);
PyModule_AddObject(pSelf, "Handshake", HANDSHAKE::init());
}
return pSelf;
}
// adds module mq to Python modules table.
void append()
{
assert(!Py_IsInitialized());
PyImport_AppendInittab("mq", &init);
}
} // namespace MQ
} // namespace Py
// test program
int main()
{
// initialize Python extension mq
Py::MQ::append();
// initialize Python interpreter
Py_Initialize();
// sample Python program
static const char *const pyProgram
= "print(\"Hello world (from Python).\")\n"
"\n"
"# import Python extension mq\n"
"import mq\n"
"\n"
"# test whether it works\n"
"def printHandshake(value):\n"
" if value == mq.Handshake.START:\n"
" print(\"MQ_HANDSHAKE_START\")\n"
" elif value == mq.Handshake.OK:\n"
" print(\"MQ_HANDSHAKE_OK\")\n"
" elif value == mq.Handshake.ERROR:\n"
" print(\"MQ_HANDSHAKE_ERROR\")\n"
" else:\n"
" print(\"Illegal MQ_HANDSHAKE value!\")\n"
"\n"
"printHandshake(mq.Handshake.START)\n"
"printHandshake(mq.Handshake.OK)\n"
"printHandshake(mq.Handshake.ERROR)\n"
"printHandshake(0)\n"
"printHandshake(1)\n"
"printHandshake(2)\n"
"printHandshake(42)\n";
// run Python interpreter
const int ret = PyRun_SimpleString(pyProgram);
if (ret) {
std::cerr << "Execution in PyRun_SimpleString() failed!\n";
}
// done
return ret;
}
Скомпилировано и протестировано в VS2013 с Python 3.6:
Hello world (from Python).
MQ_HANDSHAKE_START
MQ_HANDSHAKE_OK
MQ_HANDSHAKE_ERROR
MQ_HANDSHAKE_START
MQ_HANDSHAKE_OK
MQ_HANDSHAKE_ERROR
Illegal MQ_HANDSHAKE value!
Должен признать, что я был похож на этот образец, обманывая наш производственный код, что мы когда-то терпеливо делали, копаясь в онлайн-ресурсах. Для базового введения я рекомендую 1. Встраивание Python в другое приложение.
Корневой модуль должен быть импортирован в код Python, прежде чем его можно будет использовать (import mq в примере кода Python). В нашем продуктивном коде мы сделали это в отдельном предыдущем вызове PyRun_SimpleString(), так что нашим программистам приложений Python даже не нужно об этом заботиться.
Я разделил реализацию на несколько модулей (mq и mq.Handshake). Конечно, это можно было бы сделать еще быстрее, установив модуль mqHandshake с переменными модуля START, OK и ERROR.
@AndreasOtto Я упустил из виду тег C. Однако это выглядит очень похоже на C. Я расширил ответ на образец C (реализуя упомянутую альтернативу только с одним модулем).
Привет, я тестировал это ... используя> PyModule_AddIntConstant(pSelf, "START", MQ_HANDSHAKE_START), проблема в том ... модуль const имеет тип int, это не улучшение, добавление обычного верхнего уровня> PyModule_AddIntConstant(pSelf, "HANDSHAKE_START)",MQ_HANDSHAKE_START)
это мой ответ ... создать класс типобезопасныйIntEnum в python-C-api.
Когда я пишу оболочки Python для нашего кода C++, касающиеся
enum, я создаю (под) модуль для каждогоenum, а затем добавляю переменныеintдля соотв. счетчики. (Что-то вродеenum, похоже, не существует в Python.) Может быть, можно было бы подклассифицировать один из встроенных целочисленных типов Python, но трюк с модулем / переменной в нашем случае работает правильно. Следовательно, я никогда не пробовал подклассы.