[Tutor] Converting from Python list or tuple to C array

Michael P. Reilly arcege@shore.net
Tue, 16 Nov 1999 18:38:46 -0500 (EST)


> I need to send a list (or possibly a tuple, I haven't
> decided which will be easiest) from Python out to an
> extension module.  Here is an example of what one of the
> python function calls look like:
> 
>   myfunc('name', 2.0, 3, 4, mylist)
> 
> I know how to get the 1st four arguments into the extension
> using something along the lines of:
> 
>   PyArg_ParseTuple(args, "sfii", &str1, &float1, &int1, &int2);
> 
> But how do I get the list (or tuple)?  And once I have it, how
> do I turn the PyObject into a C array?  Note: "mylist" may be a
> list of lists of arbitrary length.
> 
> Thanks for any pointers,
> Dean.

You will want to get the value back using "O" in the format string.
  PyObject *mylist;
  PyArg_ParseTuple(args, "sfiiO", &str1, &float1, &int1, &int2, &mylist);
  if (!PySequence_Check(mylist)) {
    PyErr_SetString(PyExc_TypeError, "expected sequence");
    return NULL;
  }

You will have to decide exactly what is expected of mylist..  the C
code isn't as forgiving aa Python.  For example, do you want it to be a
list of strings, tuple of either strings or integers, a recursive list
of integers or strings or floats (union).  You can do what ever you want,
but you need to be clear in the C code.  I'll assume a sequence of
integers (could be a list or a tuple).

  PyObject *item;
  int *intarr, arrsize, index;
  ...

  /* how many elements are in the Python object */
  arrsize = PyObject_Length(mylist);
  /* create a dynamic C array of integers */
  intarr = (int *)malloc(sizeof(int)*arrsize);
  for (index = 0; index < arrsize; index++) {
    /* get the element from the list/tuple */
    item = PySequence_Getitem(mylist, index);
    /* we should check that item != NULL here */
    /* make sure that it is a Python integer */
    if (!PyInt_Check(item)) {
      free(intarr);  /* free up the memory before leaving */
      PyErr_SetString(PyExc_TypeError, "expected sequence of integers");
      return NULL;
    }
    /* assign to the C array */
    intarr[index] = PyInt_AsLong(item);
  }
  /* now use intarr and arrsize in you extension */

I hope this helps.  Let me know if you need further hints and tips.
  -Arcege

-- 
------------------------------------------------------------------------
| Michael P. Reilly, Release Engineer | Email: arcege@shore.net        |
| Salem, Mass. USA  01970             |                                |
------------------------------------------------------------------------