DECREFing and PyArray functions in C Extensions
Louis M. Pecora
pecora at anvil.nrl.navy.mil
Mon May 29 14:35:15 EDT 2000
In article <ya04s7hcox1.fsf at trymheim.ifi.uio.no>, Roger Hansen
<rogerha at ifi.uio.no> wrote:
> Now assume I have an extension where a C function should create and
> return a NumPy array.
>
> static PyObject *
> foo_retarray(PyObject *self, PyObject *args)
> {
> int length, i;
> double x;
> double* a;
> PyArrayObject *array;
>
> if(!PyArg_ParseTuple(args, "i", &length))
> return NULL;
>
> array = (PyArrayObject *)
> PyArray_FromDims(1, &length, PyArray_DOUBLE);
>
> a = (double*) array->data;
> for (i = 0; i < length; i++) {
> x = (double) i/(length-1);
> a[i] = f(x);
> }
>
> return PyArray_Return(array);
> }
>
> Should I DECREF array here before the return?
I'll take a stab at this and say, no. Using PyArray_Return(array)
automatically DECREFs the array.
> If we rewrite it like this
>
> static PyObject *
> foo_retarray2(PyObject *self, PyObject *args)
> {
> int length, i;
> double x;
> double* a;
>
> if(!PyArg_ParseTuple(args, "i", &length))
> return NULL;
>
> a = malloc(length*sizeof(double));
> for (i = 0; i < length; i++) {
> x = (double) i/(length-1);
> a[i] = f(x);
> }
>
> return PyArray_FromDimsAndData(1, &length, PyArray_DOUBLE, (char*) a);
> }
>
> I'm sure we don't have to DECREF anything. But is this a good way to
> create a NumPy array in C?
Hmmm...I would have said, yes. You malloc the memory, then return a
pointer, but you Must DECREF when any Pyarray is created, unless you
use return PyArray_Return(obj) or PyArray_BuildValue with the "N"
construct (quoting Travis). In fact, I would say you have created two
memory leaks. One with the C array through malloc and the other with
the PyArray created through PyArray_FromDimsAndData. I don't think the
latter uses the C allocated memory, but allocates its own. Not sure,
but I would check this out.
More information about the Python-list
mailing list