[Tutor] python lists to C arrays and vice versa
Viktor Hornak
hornak at csb.sunysb.edu
Mon Feb 7 15:27:56 CET 2005
Hello All,
I've been trying to find more resources/documentation about how to
convert python lists to C arrays (and vice versa) when writing a python
extension. Surprisingly, there's very little one can find about this
even though it must be a fairly common procedure. I looked through
official python guide on "Extending and Embedding the Python
Interpreter" but it's very terse on examples and the important topic on
reference counting is still not very clear. I also found one or two
examples of similar operations on this list postings (from 6 years ago!)
but they didn't quite explain all I need to know.
Here is the code I was trying to use to convert two lists (one is a list
of strings with the same length and the other is a list of doubles) to C
arrays in a C extension:
typedef char Name[5];
extern void parseMask(int, char*, Name *, double *); /* this is the
function I am
trying to wrap */
static PyObject *print_sel(PyObject *self, PyObject *args)
{
PyObject *anamestr, *xdbl;
PyObject *pylist; /* return list of 0/1 */
PyObject *item;
int nat;
int i, k;
Name *aname;
double *x;
PyArg_ParseTuple(args,"iOO", &nat, &anamestr, &xdbl);
if (!PySequence_Check(anamestr) || !PySequence_Check(xdbl)) {
PyErr_SetString(PyExc_TypeError, "expected sequence");
return NULL;
}
/* create dynamic C arrays */
aname = (Name *) malloc(sizeof(Name)*nat);
x = (double *) malloc(sizeof(double)*nat);
for (i = 0; i < nat; i++) {
/* get the element from the list*/
item = PySequence_GetItem(anamestr,i);
/* check that item != NULL, i.e. make sure it is Python string */
if (!PyString_Check(item)) {
free(aname); /* free up the memory before leaving */
free(x);
PyErr_SetString(PyExc_TypeError, "expected sequence of strings");
return NULL;
}
/* assign to the C array */
strcpy(aname[i], PyString_AsString(item));
Py_DECREF(item);
item = PySequence_GetItem(xdbl,i);
if (!PyFloat_Check(item)) {
free(aname);
free(x);
PyErr_SetString(PyExc_TypeError, "expected sequence of integers");
return NULL;
}
x[i] = PyFloat_AsDouble(item);
Py_DECREF(item);
}
Then I call the function "parseMask" (which I am trying to wrap in this
extension) which returns a C array (integer array, elements are either 0
or 1). Now I need to convert this integer array to python list and
return it back to python. Here is the code for that:
result = (int *) malloc(sizeof(int) * nat);
parseMask(...) -> returns int array result
pylist = PyTuple_New(nat);
for (i = 0; i < nat; i++) {
/* convert resulting array [0/1] to PyObject */
if (result[i] == 0)
item = PyInt_FromLong(0);
else
item = PyInt_FromLong(1);
PyTuple_SetItem(pylist, i, item);
Py_DECREF(item);
}
/* free up all arrays before leaving */
free((void *) aname);
free((void *) x);
free((void *) result);
return pylist;
I was wondering if some 'extension guru' (or whoever has experience with
writing extensions :-)) could see if the above code is correct,
especially with respect to reference counting. When I use this extension
from Python (on Fedora Core 3, Python2.3) I get the following error:
*** glibc detected *** double free or corruption (out): 0x09f724e8 ***
Aborted
This is supposed to mean some deeper memory allocation/deallocation
error. I suspect I am not creating or releasing python objects in my C
extension above correctly. Of course, it is also possible that the C
function I am wrapping (parseMask()) is not allocating memory properly,
but it works without problem when I call it from a C program.
I am sorry for this looong post, but I didn't see a way to make it
shorter and still be very specific about what I am trying to do...
Many thanks for any help,
-Viktor Hornak
More information about the Tutor
mailing list