英文:
Segfault on PyDict_New() and python >= 3.10
问题
我遇到了一个关于我的Python/C库的奇怪问题。在Python版本>=3.7且<3.10上一切正常运行。但在Python>=3.10上,Python脚本会导致段错误。在它上面运行gdb显示它在PyObject* ret = PyDict_New(); 处导致了段错误。
我已经搜索了Python 3.10和3.11的发布说明,但找不到相关信息(我正在搜索已删除的函数、更改的行为等)。
这是代码:
extern "C" PyObject* compute(const char* path, int b, int h, int f, int z, int m, int mf, char* output) {
PyObject* ret = PyDict_New();
// 一些代码
return ret;
}
如果我完全删除代码,只保留PyDict_New(),仍然会出现段错误。
有什么想法吗?我有一种直觉,觉得我可能漏掉了一些愚蠢的东西,但找不到是什么。谢谢。
英文:
I have a weird issue with my python/c library. Everything is working fine with python >=3.7 and < python 3.10.
With python >= 3.10, the python script segfaults. running gdb on it shows that is segfaults on PyObject* ret = PyDict_New();
I've searched python 3.10 and 3.11 release notes but can't find anything related (i was searching for a removed function, changed behaviour, etc).
the code is :
extern "C" PyObject* compute(const char* path, int b, int h, int f, int z, int m, int mf, char* output) {
PyObject* ret = PyDict_New();
// some code
return ret;
}
Segfault is also there if i remove entirely the code and just let PyDict_New()
Any idea ? I have a gut feeling that i'm missing something stupid, but can't find what.
Thanks
答案1
得分: 1
你可能使用了CDLL
或WinDLL
,而不是PyDLL
来加载这个库。在使用Python API时,需要使用PyDLL
来维持全局解释器锁(GIL)。我能够在Python 3.9下使用CDLL
成功加载,但在Python 3.10或3.11下却不能,这也会导致你遇到的问题,但在没有持有GIL的情况下调用Python API是未定义行为。所有这三个Python版本都可以与PyDLL
正常工作。
test.cpp
#include <Python.h>
extern "C" __declspec(dllexport)
PyObject* compute() {
PyObject* ret = PyDict_New();
return ret;
}
test.py
import ctypes as ct
lib = ct.PyDLL('./test')
lib.compute.argtypes = ()
lib.compute.restype = ct.py_object
print(lib.compute())
输出:
{}
英文:
You probably used CDLL
or WinDLL
instead of PyDLL
to load the library. Using the Python API requires using PyDLL
to maintain a lock on the GIL (Global Interpreter Lock). I was able to load with CDLL
and Python 3.9 but not 3.10 or 3.11 so that reproduces your issue, but it is undefined behavior to call Python APIs without the GIL held. All three Python versions work with PyDLL
as expected.
test.cpp
#include <Python.h>
extern "C" __declspec(dllexport)
PyObject* compute() {
PyObject* ret = PyDict_New();
return ret;
}
test.py
import ctypes as ct
lib = ct.PyDLL('./test')
lib.compute.argtypes = ()
lib.compute.restype = ct.py_object
print(lib.compute())
Output:
{}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论