>> 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).
Thanks, I didn't know that an array.array can be passed to C code as a C pointer to an array. So I'll use an array.array because this is really convenient. >> 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). Great, one headache less :) >> 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! Yes, I know :) > 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. The macro versions are preferable because they are faster? > 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? No particular reason, other than the fact that I won't need to modify these lists/tuples from python so whenever something will not change, I use a tuple because it's immutable. Or this is not a very good practice? There is no difference between lists and tuples in terms of speed I suppose (getitem, setitem, etc). Thanks a lot, Daniel -- Psss, psss, put it down! - http://www.cafepress.com/putitdown -- http://mail.python.org/mailman/listinfo/python-list