parser.cpp:
#include <python3.4/Python.h>
#include <fstream>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
extern "C"
{
PyObject* test(const char* filename)
{
size_t LIM = 1000;
PyObject* result = PyList_New(LIM);
for (size_t i = 0; i < LIM; i++) {
PyObject * t = PyList_New(0);
PyList_Append(t, PyLong_FromLong(1));
cout << i << "/" << PyList_Size(result) << " " << t << endl;
if (PyList_SetItem(result, i, t) != 0) {
cout << "!" << endl;
}
}
Py_INCREF(result);
return result;
}
}
编译:
g++ -O2 -fPIC -std=c++11 -shared -o parser_c.so parser_c.cpp -lpython3.4m
test.py:
import ctypes
import datetime
p = ctypes.CDLL('./parser_c.so')
p.test.restype = ctypes.py_object
print(p.test("asd"))
执行python3 test.py会因为分段错误而终止,而我通过调试输出获得的最后一行是
381/1000 0x7f0996bb5a88
此外,如果我不在test.py中导入日期时间或在parser.cpp中减少LIM,它可以正常工作。
我无法弄清楚为什么会这样。
有人可以帮助我吗?
答案 0 :(得分:1)
问题是ctypes释放全局解释器锁,因此对Python api函数的调用是未定义的
Python全局解释器锁在调用这些库导出的任何函数之前发布,之后重新获取。
您需要在功能开始时重新获取它,并在最后重新发布它:
PyObject* test(const char* filename)
{
PyGILState_STATE gstate = PyGILState_Ensure();
// The bulk of your code stays the same and goes here ...
PyGILState_Release(gstate);
return result;
}