I have the following python code… and want to write this Code in… Python-C-API
from enum import Enum
class MqWaitOnEventE(Enum):
NO = 0
ONCE = 1
FOREVER = 2
Thanks for help.
FIRST approach
// enum definition
PyObject *enumModO=NULL, *enumDictO=NULL, *intEnumO=NULL;
LngErrorCheckN(enumModO = PyImport_ImportModule("enum"));
LngErrorCheckN(enumDictO = PyModule_GetDict(enumModO));
LngErrorCheckN(intEnumO = PyDict_GetItemString(enumDictO,"IntEnum"));
// get 'MqWaitOnEventE '
PyObject *dictMqWaitOnEventE = NULL, *result=NULL, *base=NULL;
LngErrorCheckN(dictMqWaitOnEventE = PyDict_New());
LngErrorCheck(PyDict_SetItemString (dict, "__module__", PyUnicode_FromString("pymsgque")));
LngErrorCheck(PyDict_SetItemString (dict, "NO", OT_NEW_INT_OBJ(MQ_WAIT_NO)));
LngErrorCheck(PyDict_SetItemString (dict, "ONCE", OT_NEW_INT_OBJ(MQ_WAIT_ONCE)));
LngErrorCheck(PyDict_SetItemString (dict, "FOREVER", OT_NEW_INT_OBJ(MQ_WAIT_FOREVER)));
LngErrorCheckN(base = PyTuple_Pack(1, intEnumO));
LngErrorCheckN(result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO","MqWaitOnEventE", base, dictMqWaitOnEventE));
end with following error…
Traceback (most recent call last):
File "…/MyServer.py", line 14, in
import pymsgque
File "…/python3.7/enum.py", line 151, in __new__
enum_members = {k: classdict[k] for k in classdict._member_names}
AttributeError: 'dict' object has no attribute '_member_names'
what is this? … does python require som internals from me ?
解决方案
This is the type-safe solution for a enum in C-Module initialization file…
MqBuffer… is my string buffer class
NS(…) is a macro to create a unique namespace… I use this for all c-extern objects
.
the example will create the new MqSlaveE class in the module namespace.
PyObject* m = PyModule_Create(&ModuleDef);
...
MQ_BUF buf = MqBufferCreate(1000);
MqBufferAppendC(buf,"from enum import IntEnum\n");
MqBufferAppendC(buf,"class MqSlaveE(IntEnum):\n");
MqBufferAppendV(buf," LOOPBACK = %i\n", MQ_SLAVE_LOOPBACK);
MqBufferAppendV(buf," OTHER = %i\n", MQ_SLAVE_OTHER);
MqBufferAppendV(buf," FILTER = %i\n", MQ_SLAVE_FILTER);
MqBufferAppendV(buf," MASTER = %i\n", MQ_SLAVE_MASTER);
MqBufferAppendV(buf," USER = %i\n", MQ_SLAVE_USER);
PyObject *g, *dl, *dg, *v;
MQ_CST script = MqBufferGetC_e(buf);
g = PyImport_AddModule("__main__");
dg = PyModule_GetDict(g);
dl = PyModule_GetDict(m);
LngErrorCheckN(v = PyRun_String(script, Py_file_input, dg, dl));
Py_DECREF(v);
NS(MqSlaveE) = PyDict_GetItemString(dl,"MqSlaveE");
MqBufferDelete(&buf);
return m;
to check the object and extract the value I use a proc…
enum MqErrorE NS(Get_Enum_FromObj) (PyObject *enumT, PyObject *enumE, MQ_INT *ret) {
if (!PyObject_IsInstance(enumE, enumT)) {
PyErr_Format(PyExc_TypeError,
"input_enum_type = '%s' is not the required_enum_type = '%s'",
Py_TYPE(enumE)->tp_name, ((PyTypeObject*)enumT)->tp_name
);
return MQ_ERROR;
}
return PyObj_AsINT(enumE,ret);
}