Question

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.

Was it helpful?

Solution

The problem was in my implementation of getattro.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top