Search code examples
pythoncc-api

Pass Python list of ints to C function using Python C API


I am having an issue processing a list of ints passed to a Python C API wrapper function using Python3.6 anaconda distro on a MacOS High Sierra. I would like to convert the list of ints passed in to an array of ints that I can work with in C.

There is a similar question here Passing a Python list to C function using the Python/C API which I can get to work but processing a list of ints appears to be different.

Here is what I have so far.

static PyObject * myModule_sumIt(PyObject *self, PyObject *args) {
  PyObject *lst; 
  if(!PyArg_ParseTuple(args, "O", &lst)) {
    Py_DECREF(lst);
    return NULL;
  }

  int n = PyObject_Length(lst);
  printf("\nLength of list passed in is %d\n", n);

  int nums[n];
  int sum = 0;
  for (int i = 0; i < n; i++) {
     PyLongObject *item = PyList_GetItem(lst, i);
     sum += item;
     printf("\ni = %d\titem = %d\tsum = %d\n", i, item, sum);
     Py_DECREF(item);
  }

  Py_DECREF(lst);
  return Py_BuildValue("i", sum);
}

static PyMethodDef methods[] = {
  { "sum_it", myModule_sumIt, METH_VARARGS, "A Toy Example" },
  { NULL, NULL, 0, NULL }
};

static struct PyModuleDef myModule = {
  PyModuleDef_HEAD_INIT,
  "myModule", 
  "Demo Python wrapper",
  -1,
  methods
};

PyMODINIT_FUNC PyInit_myModule(void) {
  return PyModule_Create(&myModule);
}

This is what I get from calling the python function in the interpreter after building with distutils.

>>> import myModule
>>> myModule.sum_it([1,2,3])
Length of list passed in is 3
i = 0   item = 108078416    sum = 890306742
i = 1   item = 108078448    sum = 890306742
i = 2   item = 108078480    sum = 890306742
-1725230192

Note that my expected output should be

>>> import myModule
>>> myModule.sum_it([1,2,3])
Length of list passed in is 3
i = 0   item = 1    sum = 1
i = 1   item = 2    sum = 3
i = 2   item = 3    sum = 6
6

Solution

  • sum += item;
    

    item is not a C long or int! You have to use PyLong_AsLong:

    sum += PyLong_AsLong(item);
    

    (And sum should be a long)