C-API: A beginner's problem
Georg Brandl
g.brandl-nospam at gmx.net
Mon Mar 20 02:30:18 EST 2006
Fabian Steiner wrote:
> Georg Brandl wrote:
>> Fabian Steiner wrote:
>>> [...]
>>> for (i = 0; i <= seqlen; i++) {
>>
>> That is one iteration too much. Use
>>
>> for (i = 0; i < seglen; i++)
>>
>>> item = PySequence_Fast_GET_ITEM(seq, i);
>>
>> Now item is a PyObject*. You'll have to convert it to an integer now:
>>
>> it = PyInt_AsLong(item);
>
> Why do you use PyInt_AsLong() here? As the documentation says it returns
> a long type: long PyInt_AsLong(PyObject *io)
> On the other hand I can't find anything like PyInt_AsInt().
Python's int objects carry a long, so they can return you this long.
On most 32-bit platforms, int == long anyway, but for 64-bit you'd have
to declare list as long too.
>> if (it == -1 && PyErr_Occurred()) {
>> Py_DECREF(seq);
>
> Why is this Py_DECREF() needed? What does it do exactly? When do I have
> to call this function? Obviously, there is also Py_INCREF(). When do you
> need this function?
This is for reference counting. Since you created seq with PySequence_Fast
you "own" a reference to it (it has reference count 1). Since nothing else
references that sequence, it has to be deallocated before the function exits.
You use Py_DECREF to decrease the reference count to 0, thus telling Python
that it's safe to free the memory associated with it.
Most API functions that return a PyObject increase its reference count by 1,
leaving you in charge to do something with this ("your") reference.
Other examples of how references can be juggled with:
item = PySequence_Fast_GET_ITEM(seq, i);
PySequence_Fast_GET_ITEM does return a PyObject, but it doesn't increase the
reference count, so you don't have to DECREF item anywhere. However, if you were
to store item in a structure of some sort, you'd have to INCREF it so that
Python doesn't destroy it while it's still referenced by your structure.
PyList_SetItem(newseq, i, PyInt_FromLong(list[i]));
PyInt_FromLong() returns a new PyObject with one reference, but PyList_SetItem
"steals" that reference from you (it stores the PyObject in a structure without
increasing its reference count). Therefore, you don't own a reference to the
integer object anymore and don't have to DECREF it.
newseq = PyList_New(seqlen);
(...)
return newseq;
Here, you own a reference to newseq, but you return the object, so you have to
keep it alive. Thus, no DECREF.
>> [...]
>> There's quite a bit you can overlook, especially stale references to PyObjects.
>> I'm not even sure the code compiles or runs correctly with my corrections ;)
>
> Now, it compiles fine, without any warnings and using it in Python works
> either :-) Now I have to try to understand what the different parts are
> doing and why they are necessary.
Cheers,
Georg
More information about the Python-list
mailing list