C API: array of floats/ints from python to C and back

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Sat Dec 27 20:59:30 EST 2008


En Sat, 27 Dec 2008 22:54:52 -0200, Daniel Fetchinson  
<fetchinson at googlemail.com> escribió:

> This is the function I have, the corresponding python function will
> take two equal length lists of integers and the C function will
> compute their sum and return the result as a python tuple.
>
>
> static PyObject *func( PyObject * self, PyObject * args )
> {
>     int j, N;
>     int * src1, * src2;
>     PyObject *list1, *list2;
>
>     list1 = PyTuple_GetItem( args, 0 );
>     N = PyList_Size( list1 );
>     src1 = ( int * ) malloc( N * sizeof( int ) );
>     for( j = 0; j < N; j++ )
>     {
>         src1[j] = (int)PyInt_AsLong( PyList_GetItem( list1, j ) );
>     }
>
>     list2 = PyTuple_GetItem( args, 1 );
>     N = PyList_Size( list2 );
>     src2 = ( int * ) malloc( N * sizeof( int ) );
>     for( j = 0; j < N; j++ )
>     {
>         src2[j] = (int)PyInt_AsLong( PyList_GetItem( list2, j ) );
>     }
>
>     PyObject * tuple;
>     tuple = PyTuple_New( N );
>     for( j = 0; j < N; j++ )
>     {
>         PyTuple_SetItem( tuple, j, PyInt_FromLong( (long)( src1[j] +
> src2[j] ) ) );
>     }
>
>     free( src1 );
>     free( src2 );
>
>     return tuple;
> }

As others already said, using a Numpy array or an array.array object would  
be more efficient (and even easier - the C code gets a pointer to an array  
of integers, as usual).

> Do I have to free the memory occupied by the python objects list1 and
> list2?

No. Usually you don't do that for any Python object - just  
increment/decrement its reference count (using Py_INCREF/Py_DECREF).

> Do I have to do any refcounting for list1, list2, tuple?

In this case list1 and list2 come from PyTuple_GetItem; the docs say it  
returns a "borrowed reference" (that is, the function doesn't increment  
the refcount itself). So you don't have to decrement it yourself (and it  
isn't necesary to increment it in the first place, because the "args"  
tuple holds a reference, so the object can't disappear until the function  
exits, at least)

> Any comment on the above code will be very appreciated! If I'm pushed
> in the right direction I'm a fast learner but the beginning steps are
> always hard :)

You MUST check EVERY function call for errors!
And check the argument's type (how do you know it is a list?). Once you  
are sure the first parameter *is* a list, you may use the "macro" version  
of several functions, like PyList_GET_SIZE and PyList_GET_ITEM.
You should check that both lists have the same length too.
And you should check that elements are integers, or convertible to  
integers (in case of error, PyInt_AsLong returns -1 and PyErr_Occurred()  
is true)
To fill the resulting tuple, use PyTuple_SET_ITEM instead. BTW, why return  
a tuple and not a list?

-- 
Gabriel Genellina




More information about the Python-list mailing list