I am coding a self-defined python module embedding with C .
test.py
import my_module
column_names = ['ukey', 'OrderRef', 'orderSize']
print(my_module.my_func(column_names))
my_module.cpp (partial)
static PyObject * my_func(PyObject *self, PyObject *args)
{
Py_Initialize();
if(!Py_IsInitialized()) { std::cout<<"PythonInit failed!"<<std::endl; }
PyObject *_list = nullptr;
int len;
std::vector<std::string> c_colArray;
if (!PyArg_ParseTuple(args, "O", &_list)) {
PyErr_SetString(PyExc_TypeError, "parameter type error.");
return NULL;
}
len = PyList_Size(_list);
PyObject * _item = nullptr;
const char * _line; /* pointer to the line as a string */
for (int i = 0; i < len; i ) {
_item = PyList_GetItem(_list, i);
_line = PyUnicode_AsUTF8(_item);
std::string _elem = _line;
c_colArray.push_back(_elem);
}
Py_DECREF(_list);
return Py_BuildValue("sss", c_colArray[0].c_str(), c_colArray[1].c_str(), c_colArray[2].c_str());
}
output
('ukey', 'OrderRef', 'orderSize')
The code works fine when first calling my_func
, but it crashes when calling it again and arise Segmentation fault (core dumped)
CodePudding user response:
Py_DECREF of the input list in C code is not needed. PyArg_ParseTuple is just do parse only, just like some typecasting, not creating a new Python object.
Py_DECREF(_list);
After that, the column_names
in python will become []
. Then the my_func
is called again, the input list is an empty list in the 2nd call. So c_colArray
contains nothing, and the last c_colArray[0]
will leading segmentation fault.
The simple solution is to remove the Py_DECREF(_list);
You could easily output the column_names
in your python code like this:
import my_module
column_names = ['ukey', 'OrderRef', 'orderSize']
print(my_module.my_func(column_names))
print(column_names)
print(my_module.my_func(column_names))