Python and C, arrays

Michael P. Reilly arcege at shore.net
Tue Jun 15 14:16:55 EDT 1999


John Fisher <jfisher at are.berkeley.edu> wrote:
: Hey folks,

: I've run into a problem with a module I'm writing in C.  Basically, I
: need to be able to convert Python tuples or lists (it's unimportant
: which) into C arrays.  I know at compile-time the type of the array (and
: that the tuple or list will be homogeneous, and of compatible type), but
: I don't know the size.

: I then need to find a way to take a C array and stuff it back into a
: Python tuple or list.  I have some ideas involving using "stack-like"
: lists or tuples in Python, with a "pop" function which I could call from
: C, repeated in a loop to get everything.  But this seems overly complex,
: and indeed like it has the potential to become truly hideous.

: I would imagine these two tasks are actually quite common.  Is there
: some simpler way to do either?  Dare I hope that PyArg_ParseTuple and
: Py_BuildValue can do it?

Use the Abstract Layer's PySequence_*() functions in the C API
 (http://www.python.org/doc/current/api/sequence.html)

PyObject_Length() will give you the number of elements in a tuple or
list.  And from the other direction (if you do not know the size of the
array), use (sizeof(array)/sizeof(array[0])).

Here are some specific converters for you (from a Python sequence to a
C array of PyObject* and back).

  int convert_PySeq2C(seq, array)
    PyObject *seq;
    PyObject ***array;
    { int i, n;
      PyObject *tmp;

      n = PyObject_Length(seq);
      *array = (PyObject *)malloc(n * sizeof(PyObject *));
      for (i = 0; i < n; i++) {
        tmp = PySequence_GetItem(seq, i);  /* not a 'borrowed' reference */
        if (tmp == NULL) {
          free(*array);
          *array = NULL;
          return -1; /* exception set already */
        }
        Py_INCREF(tmp);
        (*array)[i] = tmp;
      }
      return n;
    }

Converting back to Python is a little simplier:

  PyObject *convert_PySeq2C(array, n)
    PyObject *array[];
    int n;
    { int i;
      PyObject *result;

      result = PyTuple_New(n);
      if (result != NULL) {
        for (i=0; i < n; i++)
          PyTuple_SetItem(result, i, array[i]); /* increments the ref count */
      }
      return result;
    }

There will be other, more efficient, means that would be tailored to
your app.

  -Arcege




More information about the Python-list mailing list