Python与动态扩展C++类
我在使用Python时遇到了一个问题,涉及到我自定义的类型、函数和属性。
当我在Python中想给我的自定义类型(比如Vector4)设置一个属性时,我的代码在const char* attribute_name
这个参数上得到了NULL(是的,我已经导入了我的模块)。
奇怪的是,当我在设置函数中硬编码属性名称时,我收到了一个错误:
SystemError: error return without exception set
我确实看到对象在Python中被创建(在C++中也是),所以我不认为这是问题所在。如果setattro
钩子成功设置了属性,我会返回1,而且我看到代码在C++端被调用并设置了属性。在设置属性时没有出现错误或异常。
另外,当我在Python中调用我类的实例上的一个函数时,它调用的是在tp_getattro
中设置的函数,而不是检查字典。
我不太确定为什么会这样,可能是因为我在设置一个字典并把我的函数放在里面,而不是通过PyModuleDef
数组来做,因此在调用PyType_Ready
时函数没有被看到。
有没有人知道这可能是什么原因?我们使用的是Python 3.2。
相关信息:
我有一个基础类型(tp_new
和tp_dealloc
),然后我在运行时创建派生类型。派生类型有一个字典,tp_base
,tp_getattro
和tp_setattro
。
这是函数如何绑定到Python类/类型的:
PyMethodDef newMethod;
newMethod.ml_doc = newMethod.ml_name = funcName;
newMethod.ml_flags = METH_VARARGS;
newMethod.ml_meth = pythonFunc;
PyGeneralObj* selfFake = PyObject_New(PyGeneralObj, &MetaEngineType);
selfFake->className = className;
selfFake->funcName = funcName;
Py_INCREF((PyObject*)selfFake);
PyObject *func = PyCFunction_New(&newMethod, (PyObject*)selfFake);
PyObject *method = PyInstanceMethod_New(func);
ErrorIf((method == NULL), "Python: Cannot create instance function. %s",
funcName);
ErrorIf((PyDict_SetItem(classObj->m_pyClassType->tp_dict,
PyReturnStr(newMethod.ml_name), method) == -1),
"Python: Cannot create function in dictionary.");
Py_DECREF(func);
Py_DECREF(method);
其中funcName和className是const char*。pythonFunc是一个通用的Python函数,用于处理调用我们所有绑定到元系统的函数。classObj是指向一个PythonClass的指针,它有一个成员m_pyClassType(类型为PyTypeObject)。
PyGeneralObj
是一个新对象,有两个const char*和一个void*(这是C++中的对象)。
我执行PyType_Ready
时没有错误,然后增加我的类型。接着我把这个对象添加到通过PyImport_ImportModule
获得的模块PyObject中。我把我的主模块附加到运行时,并初始化Python并导入我的模块。
如果需要更多信息或代码,我可以再发一些。我希望这些内容能让人明白,这是我第一次在StackOverflow上发帖。
为了澄清,我们希望有动态属性,这些属性完全在C++端解析。对于函数,我希望能够覆盖PyObject* self
参数,以便我可以获取需要调用的函数的字符串名称。
我们不想使用像Boost、Cython等第三方库或接口。
1 个回答
问题出在我对getattro这个函数的实现上。