[capi-sig] Reference counts and dictionary creadtion

Stefan Behnel python_capi at behnel.de
Tue Dec 29 23:25:23 CET 2009


Dan Colesworthy, 29.12.2009 21:38:
> I am attempting to write a python extension in C to "glue" the ASIO SDK
> to python 2.5.4.  However I am really confused about reference counts.

You might want to take a look into Cython, a Python-like language that is 
well suited for writing very fast C library wrappers. Besides many other 
features, it will do all the reference counting for you and generates code 
that works in Python 2 and Python 3.


> Below is a code snippet that "seems" to work, however I suspect that
> some of the object reference counts have been incremented too many
> times.
>  
> 
> static PyObject *
> 
> getAsioInfo(PyObject *self, PyObject *args) {
> 
>    PyObject *dict = Py_None;
> 
>    if (loadAsioDriver (ASIO_DRIVER_NAME)) {
> 
>       if (ASIOInit (&asioDriverInfo.driverInfo) == ASE_OK){
> 
>          dict = PyDict_New();
> 
>          PyDict_SetItem(dict,
> 
>                         PyString_FromString("asioVersion"),

Yes, this doesn't work. PyDict_SetItem() doesn't steal the reference, so 
you end up with a dangling reference to the just created string. Same for 
the other objects created below:

> PyInt_FromLong(asioDriverInfo.driverInfo.asioVersion) );
> 
>          PyDict_SetItem(dict, 
> 
>                         PyString_FromString("driverName"),
> 
>  
> PyString_FromString(asioDriverInfo.driverInfo.name) );

You need to assign each object to a variable, call SetItem() on it, and 
then Py_DECREF() it afterwards.

Note that there is also a special function PyDict_SetItemString() that 
accepts a char* as key and creates the Python string object internally.

Also note that the PyString_*() functions are likely not what you want to 
use in Python 3.

Stefan



More information about the capi-sig mailing list