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  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to