views:

69

answers:

2
+4  A: 

Your c++ code seems to be a classic wrapper using the official C-API and it's a bit weird since ctypes is usually used for using classic c types in python (like int, float, etc...).

I use personnally the C-API "alone" (without ctypes) but on my personnal experience, you don't have to worry about the reference counter in this case since you are returning a native python type with Py_BuildValue. When a function returns an object, the ownership of the returned object is given to the calling function.

You have to worry about Py_XINCREF/Py_XDECREF (better than Py_INCREF/Py_DECREF because it accepts NULL pointers) only when you want to change ownership of the object :

For example, you have created a wrapper of a map in python (let's call the typed object py_map). The element are of c++ class Foo and you have created an other python wrapper for them (let's call it py_Foo). If you create a function that wrap the [] operator, you are going to return a py_Foo object in python :

F = py_Map["key"]

but since the ownership is given to the calling function, you will call the destructor when you delete F and the map in c++ contains a pointer to a deallocated objet !

The solution is to write in c++ in the wrapper of [] :

...
PyObject* result; // My py_Foo object
Py_XINCREF(result); // transfer the ownership
return result;
}

You should take a look at the notion of borrowed and owned reference in python. This is essential to understand properly the reference counter.

Elenaher
But you create a python-c module right? I wanted to skip that and with ctypes you can just `ctypes.cdll.LoadLibrary('some.so')`. So the return type handling is different. With ctypes it's `ctypes.py_object`. Then I use the cast function and I'm not sure how the ref count is handled correctly. See my edit.
tauran
Yes indeed, that may be a bit more complicated... I tried to read the code source of cast() but I hadn't enough time to investiagte properly. I will try to take a look when I'll have enough time and edit my answer if I find something that prove that ctypes takes the ownership (if it's the case, maybe you should consider creating directly a python-c object to eliminate these problems. That's quite easy since you are already working with PyObject)
Elenaher
A: 

On further research I found out that one can specify the return type of the function. http://docs.python.org/library/ctypes.html#callback-functions This makes the cast obsolete and the ref count is no longer a problem.

clib = ctypes.cdll.LoadLibrary('some.so')
c_foo = clib.c_foo
c_foo.restype = ctypes.py_object

As no additional answers were given I accept my new solution as the answer.

tauran