[Tutor] Refcount in C extensions

Stefan Behnel stefan_ml at behnel.de
Fri Jan 14 20:11:51 CET 2011


Izz ad-Din Ruhulessin, 14.01.2011 19:49:
> Thanks for your quick reply and clearing the issue up for me. Using your
> answer, I rewrote the function to this:
>
> double Py_GetAttr_DoubleFromFloat(PyObject *obj, const char *attr)
>>
>> {
>>
>> PyObject *get_attr, *py_float;
>>
>> int has_attr;
>>
>>
>>> //Check if the given object has the given attribute.
>>
>> has_attr = PyObject_HasAttrString(obj, attr);
>>
>> if (has_attr == False) {
>>
>> return -9999.0;
>>
>> }
>>
>>
>>> //Get our attribute and convert it to a double.
>>
>> get_attr = PyObject_GetAttrString(obj, attr);

Note that HasAttr() calls GetAttr() internally, so it's actually faster to 
call GetAttr() and check for an exception (and clear it). That's basically 
how HasAttr() works, except that it doesn't tell you the result if the 
attribute existed.


>> py_float = PyNumber_Float(get_attr);
>>
>> if (py_float == NULL) {
>>
>> Py_DECREF(get_attr);
>>
>> Py_XDECREF(py_float);

You already know that py_float is NULL, so Py_XDECREF() is a no-op.


>> return -9999.0;
>>
>> }
>>
>> double output = PyFloat_AsDouble(py_float);
>>
>>
>>> //Garbage collect
>>
>> Py_DECREF(get_attr);
>>
>> Py_XDECREF(py_float);

py_float cannot be NULL at this point, so the Py_XDECREF() will compile 
into Py_DECREF().


> (False is 0)

In that case, better write 0 instead.


> Regarding your Cython suggestion, as a matter of coincidence I have been
> reading about it in the past few days. I'm in doubt of using it however,
> because I have a lot of native C code that would require rewriting if I
> switched to Cython.

No need for that, Cython can call external C code natively. So you can make 
the switch step by step.


> On the other hand, your example shows that such a
> one-time rewrite will pay-off big time in future development speed.

It usually does, yes. It often even pays off immediately because a rewrite 
tends to be pretty straight forward (basically, read and understand the C 
code, rip out all low-level stuff and replace the rest with simpler code), 
and while doing so, some bugs tend to disappear, the code becomes simpler, 
safer and often also faster, and new features appear while you're at it.

Stefan



More information about the Tutor mailing list