I’ve got two different Python extension modules; let’s call them A and B. Module A contains a storage class type called container that I want to use within Module B as the return type of a class method.
I can’t seem to find any documentation on how I’m supposed to do this. I roughly followed this article to create the modules/classes, except I didn’t declare all the methods as static, so they would be accessible: http://nedbatchelder.com/text/whirlext.html
My question is then, how do I go about creating an instance of container that I can pass back as the PyObject* return value of a class method in module B? The container definition looks like this:
typedef struct {
PyObject_HEAD
storageclass* cnt_;
} container;
I tried simply doing the following within the method in question, where container_init is the method I have registered as tp_init for the container class:
pycnt::container* retval;
pycnt::container_init(retval, NULL, NULL);
return (PyObject*)retval;
However according to the Python interpreter I’m getting back the class that I called the method on. (i.e., myclassinstance.mymethod() is returning myclassinstance).
I’m obviously going about this the wrong way, but I have no idea what the right way is. Any suggestions? Just to cut anybody off that’s going to suggest it – no I am not interested in using SWIG or Boost::Python. I tried that already and the underlying storage class for container didn’t play nicely with either (SWIG couldn’t even parse it). So far doing the extensions myself has been pretty painless, but I’m stumped on this one.
Your problem is that
type->tp_initdoesn’t do what you want.type->tp_initis called after an object is allocated to do the instantiation. You’d first have to allocate the object usingtype->tp_new, then pass that object as the first argument totype->tp_init. Since you pass an uninitialized pointer totp_init, all bets are off. You typically don’t call either function directly, though, and instead call one ofPyObject_Call*()on the type object itself to create a new instance. Or provide a normal C function to create a new instance, a laPyFoo_New().That said, the usual way to do intercommunication between two extension modules is to do it through the Python API. If you want module B to import and use module A, you call
PyImport_Import()to get the module object,PyObject_GetAttrString()to get the type object you care about, and one ofPyObject_Call*()to instantiate it. Any place you want to store a pointer to that type, you would just take aPyObject *.