我尝试将Python解释器嵌入到C中。为了测试这一点,我创建了一个共享库,并尝试用ctypes在Python中加载这个库。不幸的是,这不起作用,我想知道为什么。
下面是一个例子c -代码:
#ifdef __cplusplus
extern "C" {
#endif
#include <Python.h>
int run_py(void);
int run_py2(void);
int
run_py(void)
{
printf("hello from run_py\n");
return 42;
}
int
run_py2(void)
{
printf("entering c-function: run_py()\n");
Py_Initialize();
PyRun_SimpleString("print('hello world')");
return 0;
}
#ifdef __cplusplus
}
#endif
字符串
所以我用gcc把它编译成“mylib.so“,并使用python3.7-config --cflags和--ldflags进行链接等等。
下面是我用来加载这个的Python代码。
import ctypes as c
import os
import sys
if __name__ == '__main__':
print("running shared-lib integration test with python:\n{}".format(sys.version))
path = os.path.dirname(os.path.realpath(__file__))
dllfile = os.path.join(path, 'mylib.so')
dll = c.CDLL(str(dllfile))
print("loaded CDLL")
dll.run_py.restype = c.c_int
dll.run_py2.restype = c.c_int
print("now calling dll.run_py()...")
rv = dll.run_py()
print("called dll.run_py: rv={}".format(rv))
print("now calling dll.run_py2()...")
rv2 = dll.run_py2()
print("called dll.run_py2: rv={}".format(rv2))
型
所以这只是加载函数run_py和run_py2并执行它们。这是输出.
running shared-lib integration test with python:
3.7.1 (default, Oct 22 2018, 10:41:28)
[GCC 8.2.1 20180831]
loaded CDLL
now calling dll.run_py()...
hello from run_py
called dll.run_py: rv=42
now calling dll.run_py2()...
entering c-function: run_py()
Segmentation fault (core dumped)
型
所以基本上这会导致在调用run_py2时出现segfault。这是因为调用了PyRun_SimpleString
。但是如果我把它编译成一个独立的C程序,一切似乎都很好。我真的很想知道为什么会发生这种情况......但目前我没有任何想法,所以这里非常感谢任何反馈。
BR jrsm
1条答案
按热度按时间kcugc4gi1#
我对你的代码做了一点修改。另外,我在 Win 上进行测试(因为这对我来说更方便),但我相信在 Nix 上也是一样的。
字符串
型
输出:
型
这个问题又出现了。首先,我以为是[Python. Python]:void,Finalization,and Threads - void Py_Initialize()调用。但后来我想起了[Python. Python]:class ctypes.PyDLL(name,mode=DEFAULT_MODE,handle=None),它声明(强调是我的):
这个类的示例的行为类似于CDLL示例,除了Python GIL在函数调用期间 * 不 * 释放,并且在函数执行后检查Python错误标志。如果设置了错误标志,则引发Python异常。
因此,这只对直接调用Python C API函数有用。
将 code00.py 中的 CDLL 替换为 PyDLL,得到:
型
输出(Nix 带 PyDLL):
型
可能相关: