-4

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 <module>
    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 ?

3
  • 2
    Is this not enough? Commented Nov 22, 2018 at 11:40
  • "Is this not enough?"… I'm not 100% sure… but it seems… the documentation missing same "hints"… for the problem from above :-) Commented Nov 22, 2018 at 13:33
  • Your issue is that you need to call intEnumO.__prepare__ to get a suitable dictionary, not PyDict_New Commented Apr 16, 2020 at 11:03

1 Answer 1

1

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);                                                                                   
} 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.