在 Python C 扩展中创建 PyList_New 时出现段错误
Segment fault when creating PyList_New in Python C extention
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,它可以正常工作。
我不明白为什么会这样。
有人可以帮助我吗?
问题是 ctypes 释放了全局解释器锁,因此对 Python api 函数的调用未定义
The Python global interpreter lock is released before calling any function exported by these libraries, and reacquired afterwards.
函数开始时需要重新获取,结束时重新释放:
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;
}
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,它可以正常工作。
我不明白为什么会这样。
有人可以帮助我吗?
问题是 ctypes 释放了全局解释器锁,因此对 Python api 函数的调用未定义
The Python global interpreter lock is released before calling any function exported by these libraries, and reacquired afterwards.
函数开始时需要重新获取,结束时重新释放:
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;
}