So I'm running into a problem with my custom types, functions and attributes in Python.
When I'm in Python, and I want to set an attribute on one of my custom types (for example Vector4), my code gets a NULL for the const char* attribute_name
argument (and yes, I am importing my module).
Oddly enough, when I hard code the attribute name in my setter function, I get the error:
SystemError: error return without exception set
I do see the object getting created in Python (and again in C++), so I don't think that's the problem. I do return 1 if the setattro hook did successfully set the attribute in C++, and I see the code getting called and setting the attribute on the C++ side. There are no errors/exceptions that are raised when the attribute is being set.
Additionally, when I call a function on the instance of my class in Python, it calls the function set in tp_getattro
instead of checking the dictionary.
I'm not entirely sure why, maybe it's because I'm setting a dictionary and putting my functions in there, instead of doing it via a PyModuleDef
array, thus functions aren't being seen when PyType_Ready
is called.
Does anyone have any idea why this might be happening? We're using Python 3.2.
Relevant:
I have a base type (tp_new
and tp_dealloc
) and then I am creating derived types at runtime. The derived types have a dictionary, tp_base
, tp_getattro
and a tp_setattro
.
This is how functions are bound to Python class/types:
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);
Where funcName and className are const char*. pythonFunc is a generic python function that handles calling all of our functions that are bound to our meta system. classObj is a pointer to a PythonClass which has a member m_pyClassType (a typeof PyTypeObject).
PyGeneralObj
is a new object has two const char* and a void* (this is the object in C++)
I do PyType_Ready
and get no errors, and then increment my type. I then add the object to the module PyObject that I'm given from PyImport_ImportModule
. I do append my main module to the runtime and initalize python and import my module.
If more information/code is needed, I can post some more. I hope this makes sense, this is my first time posting on stackoverflow.
For clarification, we want to have dynamic attributes that are completely resolved on the C++ side. And for functions, I want to be able to override the PyObject* self
argument so that I can get the string name of the function that needs to be called.
We don't want to use third party libraries/interfaces like Boost, Cython and whatever.
The problem was in my implementation of getattro.