Question

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.

Was it helpful?

Solution

Your problem is that type->tp_init doesn't do what you want. type->tp_init is called after an object is allocated to do the instantiation. You'd first have to allocate the object using type->tp_new, then pass that object as the first argument to type->tp_init. Since you pass an uninitialized pointer to tp_init, all bets are off. You typically don't call either function directly, though, and instead call one of PyObject_Call*() on the type object itself to create a new instance. Or provide a normal C function to create a new instance, a la PyFoo_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 of PyObject_Call*() to instantiate it. Any place you want to store a pointer to that type, you would just take a PyObject *.

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