I'm writing a Python extension in C. My function takes a list of Numpy arrays (that contain integers) as a parameter. I go through the list, get each array, increase the reference, get the C pointers to the array and then decrease the reference.
if (!PyArg_ParseTuple(args, "O", &list))
return NULL;
long nb_arrays = PyList_Size(list);
arrays = (int **) malloc(nb_arrays * sizeof(int *));
for (i = 0; i < nb_arrays; i++)
{
PyArrayObject *array = (PyArrayObject *) PyList_GetItem(list, i);
Py_INCREF(array);
arrays[i] = (int *) PyArray_DATA(array);
Py_DECREF(array);
}
After this loop, I'm using the pointers to do my calculations. Is it correct or must I wait for the end of the function to decrease the reference counts?
PyArray_DATA
has no effect on the reference count of the array it is applied to. Furthermore, when the list that was passed to your function was created, the reference count of each of the arrays in it was increased by one. So while they don't hurt much, those Py_INCREF
and Py_DECREF
are completely unnecessary, you can get rid of both of them.
You typically have to Py_INCREF
an object when you are going to pass it to a function that steals the reference (i.e. takes ownership of it and assumes the responsibility of decreasing the count when it is done with needing it).
You typically have to Py_DECREF
any temporary objects you have created inside a function, that are not part of your returns, and that are not needed by any of the returns.
You rarely (if ever) have to first Py_INCREF
something to later Py_DECREF
it. You can probably write some messed up multi-threaded code releasing the GIL that makes this parragraph not true, but in general everything passed to your function was part of a tuple (if a positional argument) or a dictionary (if a keyword argument), so it had its reference count increased when the call was made. That tuple and dictionary will not be destroyed until your function returns, so it is safe to assume that all items passed to you will not be garbage collected midway through your function, i.e. you are borrowing that reference, hence there is no need to explicitly increase the reference count just to access the objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With