Python и динамически расширяемые классы C ++ - PullRequest
1 голос
/ 14 октября 2011

Итак, я столкнулся с проблемой с моими пользовательскими типами, функциями и атрибутами в 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 и другие.

1 Ответ

0 голосов
/ 19 октября 2011

Проблема была в моей реализации getattro.

...