python - 在 Python C 扩展中创建 PyList_New 时出现段错误

标签 python segmentation-fault python-c-api

解析器.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

测试.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 中导入 datetime 或在 parser.cpp 中减少 LIM,它也可以正常工作。

我不明白为什么会发生这种情况。

有人可以帮助我吗?

最佳答案

问题在于 ctypes 释放了全局解释器锁,因此对 Python api 函数的调用未定义

From the documentation :

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;
}

关于python - 在 Python C 扩展中创建 PyList_New 时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35774011/

相关文章:

python - 如何使用 Python/C API 将 numpy.ndarray 转换为 cv::Mat?

python - 在 C/API 中指定 Python 函数签名

python - 如何消除文件: python中的重复行

javascript - 如何使用 Angular 进行 HTTP 基本身份验证

python - 如何正确覆盖 Django 中的应用程序?

c++ - 我的动态数组在 free() 时有 SIGSEGV,但可以访问吗?

python - 从 C 扩展返回 C 字符串数组

python - 使用 numpy 滚动最大值

c - Malloc 分配超出范围的内存地址

c++ - 带有字符串数组的段错误c++