[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