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
_______________________________________________ Tutor maillist - [email protected] http://mail.python.org/mailman/listinfo/tutor
