I am to build a C module for Python 3.7, that swaps two list elements. Here is my code, where indexes of two elements and list are read:
static PyObject *st_change(PyObject *self, PyObject *args){
PyObject *pList;
PyObject *tmp1;
PyObject *tmp2;
int i,j;
Py_ssize_t n;
if (!PyArg_ParseTuple(args, "O!ll", &PyList_Type, &pList,&i,&j)) {
PyErr_SetString(PyExc_TypeError, "parameters are wrong.");
return NULL;
}
n = PyList_Size(pList);
tmp1 = PyList_GetItem(pList,i);
tmp2 = PyList_GetItem(pList,j);
PyList_SetItem(pList,i,tmp2);
PyList_SetItem(pList,j,tmp1);
Py_INCREF(pList);
return pList;
}
This works for one-dimensional lists, but when I try to swap elements in list of lists, Python shuts down. For example, when a call
my_module.st_change([1,2,3],0,1)
the result is
[2,1,3]
and when I call
my_module.st_change([[1,2,3],[4,5,6],[7,8,9]],0,1)
python shell restsarts
I am completely new to C Python API, so would really appreciate if someone could point me in the right direction. Thank you
You're losing a reference to tmp1
. PyList_SetItem
discards a reference to the item already in that position, so when you do PyList_SetItem(pList,i,tmp2);
you tmp1
gets decreffed and probably deallocated. You get away with it for int
because there are typically lots of references to small int values.
Before the calls to PyList_SetItem
add Py_INCREF(tmp1); Py_INCREF(tmp2);