Итак, я столкнулся с проблемой с моими пользовательскими типами, функциями и атрибутами в Python.
Когда я нахожусь в Python и хочу установить атрибут для одного из моих пользовательских типов (например, Vector4), мой код получает значение NULL для аргумента const char* attribute_name
(и да, я импортирую свой модуль) ,
Как ни странно, когда я жестко кодирую имя атрибута в своей функции сеттера, я получаю ошибку:
SystemError: error return without exception set
Я вижу, что объект создается в Python (и снова в C ++), поэтому я не думаю, что это проблема. Я возвращаю 1, если ловушка setattro успешно установила атрибут в C ++, и я вижу, как вызывается код и задается атрибут на стороне 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 являются постоянными символами *. pythonFunc - это универсальная функция python, которая обрабатывает вызов всех наших функций, связанных с нашей мета-системой. classObj - указатель на PythonClass, который имеет член m_pyClassType (тип PyTypeObject).
PyGeneralObj
это новый объект, имеющий два const char * и void * (это объект в C ++)
Я делаю PyType_Ready
и не получаю ошибок, а затем увеличиваю свой тип. Затем я добавляю объект в модуль PyObject, полученный от PyImport_ImportModule
. Я добавляю свой основной модуль во время выполнения, инициализирую python и импортирую мой модуль.
Если потребуется дополнительная информация / код, я могу опубликовать еще. Надеюсь, это имеет смысл, это моя первая публикация на stackoverflow.
Для пояснения, мы хотим иметь динамические атрибуты, которые полностью разрешаются на стороне C ++. А для функций я хочу иметь возможность переопределить аргумент PyObject* self
, чтобы я мог получить строковое имя функции, которую нужно вызвать.
Мы не хотим использовать сторонние библиотеки / интерфейсы, такие как Boost, Cython и другие.