SWIG C-to-Python Int Array

Adam picture Adam · Apr 25, 2011 · Viewed 9.2k times · Source

I am trying to access a C function with the following prototype from python using swig:

int cosetCoding(int writtenDataIn, int newData, const int memoryCells, int *cellFailure, int failedCell);

Swig creates the .so with no problems and I can import it into python, but when I try to access it with the following:

 cosetCoding.cosetCoding(10,11,8,[0,0,0,0,0,0,0,0],0)

I get the following traceback:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: in method 'cosetCoding', argument 4 of type 'int *'

The pointer is supposed to be an int array with size defined by memoryCells

Answer

Mark Tolonen picture Mark Tolonen · Apr 26, 2011

Use ctypes if you can. It is simpler. However, since you asked for SWIG, what you need is a typemap describing how to handle the int*. SWIG doesn't know how many integers may be pointed to. Below is hacked from an example in the SWIG documentation on multi-argument typemaps:

%typemap(in) (const int memoryCells, int *cellFailure) {
  int i;
  if (!PyList_Check($input)) {
    PyErr_SetString(PyExc_ValueError, "Expecting a list");
    return NULL;
  }
  $1 = PyList_Size($input);
  $2 = (int *) malloc(($1)*sizeof(int));
  for (i = 0; i < $1; i++) {
    PyObject *s = PyList_GetItem($input,i);
    if (!PyInt_Check(s)) {
        free($2);
        PyErr_SetString(PyExc_ValueError, "List items must be integers");
        return NULL;
    }
    $2[i] = PyInt_AsLong(s);
  }
}

%typemap(freearg) (const int memoryCells, int *cellFailure) {
   if ($2) free($2);
}

Note that with this definition, when called from Python leave out the memoryCells parameter and just pass an array such as [1,2,3,4] for cellFailure. The typemap will generate the memoryCells parameter.

P.S. I can post a fully working example (for Windows) if you want it.