Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中嵌入Python解释器会导致在加载ctypes时出现segfault_Python_C_Ctypes - Fatal编程技术网

在C中嵌入Python解释器会导致在加载ctypes时出现segfault

在C中嵌入Python解释器会导致在加载ctypes时出现segfault,python,c,ctypes,Python,C,Ctypes,我尝试将Python解释器嵌入到C中。 为了测试这一点,我创建了一个共享库和 尝试在Python中用ctypes加载这个。不幸的是,这不是 工作,我想知道为什么 下面是一个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"

我尝试将Python解释器嵌入到C中。 为了测试这一点,我创建了一个共享库和 尝试在Python中用ctypes加载这个。不幸的是,这不是 工作,我想知道为什么

下面是一个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
因此,这只是加载函数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\u SimpleString
。 但是如果我把它编译成一个独立的C程序 一切似乎都很好。我真的 想知道为什么会发生这种情况。。。但是现在我 我们有自己的想法,所以这里非常感谢您的反馈


BR jrsm

我稍微更改了您的代码。另外,我正在测试Win(因为这对我来说更方便),但我确信在Nix中情况是一样的

dll.c:

#包括
#包括
#定义PRINT\u MSG\u 0()printf(“从C-[%s](%d)-[%s]\n”、\uuuu文件、\uuuu行、\uuu函数)
#如果已定义(_WIN32)
#定义DLL\u导出\u API\u declspec(dllexport)
#否则
#定义DLL\u导出\u API
#恩迪夫
#如果已定义(uuu cplusplus)
外部“C”{
#恩迪夫
DLL_导出_API int test0(无效);
DLL_导出_API int test1(无效);
#如果已定义(uuu cplusplus)
}
#恩迪夫
int test0(无效){
打印消息0();
返回42;
}
int test1(无效){
打印消息0();
Py_初始化();
打印消息0();
PyRun_SimpleString(“打印(\'Hello world!!!\”);
打印消息0();
返回0;
}
code.py:

#/usr/bin/env蟒蛇3
导入系统
从ctypes导入CDLL\
c_int
DLL=“./DLL.so”
def main():
dll\U dll=CDLL(dll)
test0\u func=dll\u dll.test0
test0_func.argtypes=None
test0_func.restype=c_int
test1\u func=dll\u dll.test1
test1_func.argtypes=None
test1_func.restype=c_int
打印(“调用{:}…”格式(test0\u func.\uuuuu name\uuuu))
res=test0_func()
打印(“{:}返回{:d}”。格式(test0\u func.\uuu name\uuuu,res))
打印(“调用{:}…”格式(test1函数名)
res=test1_func()
打印(“{:}返回{:d}”。格式(test1\u func.\uuu name\uuuu,res))
如果名称=“\uuuuu main\uuuuuuuu”:
打印(“Python{:s}on{:s}\n.”格式(sys.version,sys.platform))
main()
输出


我把你的代码改了一点。另外,我正在测试Win(因为这对我来说更方便),但我确信在Nix中情况是一样的

dll.c:

#包括
#包括
#定义PRINT\u MSG\u 0()printf(“从C-[%s](%d)-[%s]\n”、\uuuu文件、\uuuu行、\uuu函数)
#如果已定义(_WIN32)
#定义DLL\u导出\u API\u declspec(dllexport)
#否则
#定义DLL\u导出\u API
#恩迪夫
#如果已定义(uuu cplusplus)
外部“C”{
#恩迪夫
DLL_导出_API int test0(无效);
DLL_导出_API int test1(无效);
#如果已定义(uuu cplusplus)
}
#恩迪夫
int test0(无效){
打印消息0();
返回42;
}
int test1(无效){
打印消息0();
Py_初始化();
打印消息0();
PyRun_SimpleString(“打印(\'Hello world!!!\”);
打印消息0();
返回0;
}
code.py:

#/usr/bin/env蟒蛇3
导入系统
从ctypes导入CDLL\
c_int
DLL=“./DLL.so”
def main():
dll\U dll=CDLL(dll)
test0\u func=dll\u dll.test0
test0_func.argtypes=None
test0_func.restype=c_int
test1\u func=dll\u dll.test1
test1_func.argtypes=None
test1_func.restype=c_int
打印(“调用{:}…”格式(test0\u func.\uuuuu name\uuuu))
res=test0_func()
打印(“{:}返回{:d}”。格式(test0\u func.\uuu name\uuuu,res))
打印(“调用{:}…”格式(test1函数名)
res=test1_func()
打印(“{:}返回{:d}”。格式(test1\u func.\uuu name\uuuu,res))
如果名称=“\uuuuu main\uuuuuuuu”:
打印(“Python{:s}on{:s}\n.”格式(sys.version,sys.platform))
main()
输出


看起来您混合了两种不同的东西,嵌入Python和扩展Python。如果您的库扩展了Python(即可从Python内部加载),则不应尝试在其中嵌入Python解释器(除非您需要两个独立的、不相关的Python解释器,我对此表示怀疑)。是的,您是对的,最终我不会使用两个Python interpeter。。。只有C中的共享库(因此Python嵌入到C中)。然而,我尝试将此作为第一个测试(出于好奇),现在我想了解它为什么会损坏;-)看起来您混合了两种不同的东西,嵌入Python和扩展Python。如果您的库扩展了Python(即可从Python内部加载),则不应尝试在其中嵌入Python解释器(除非您需要两个独立的、不相关的Python解释器,我对此表示怀疑)。是的,您是对的,最终我不会使用两个Python interpeter。。。只有C中的共享库(因此Python嵌入到C中)。然而,我尝试将此作为第一个测试(出于好奇),现在我想了解它为什么会损坏;-)感谢您花时间和耐心来测试这一点。我更换了CDLL,它似乎可以工作,所以这很好,谢谢!你知道为什么会发生这种故障吗?你所说的只对python c api函数调用有用是什么意思?我个人不是什么意思,它是官方文档中的粘贴。您知道Python代码在GIL下运行,这意味着每个函数(包括PyRun_SimpleString)都应该这样运行。CDLL“阻止”GIL,所以我猜这是未定义的行为。要了解更多详细信息,您可能需要浏览Python源代码。是的,我认为很难判断发生了什么。然而,我认为有2个GIL,一个用于嵌入式python,另一个用于其他。我的意思是,当使用多处理模块时,因此,生成多个python进程时,也应该有超过1个GIL。不,每个进程都有一个GIL(可以是活动的/非活动的)。我们的情况就是这样。但问题是,一个应该在GIL下运行的函数(PyRun_SimpleString)并没有这样做,因为它是由CDLL发布的。也许它引用了一些po
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)
(py35x64_test) e:\Work\Dev\StackOverflow\q053609932>"c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x64

(py35x64_test) e:\Work\Dev\StackOverflow\q053609932>dir /b
code.py
dll.c

(py35x64_test) e:\Work\Dev\StackOverflow\q053609932>cl /nologo /DDLL /MD /Ic:\Install\x64\Python\Python\3.5\include dll.c  /link /NOLOGO /DLL /OUT:dll.so /LIBPATH:c:\Install\x64\Python\Python\3.5\libs
dll.c
   Creating library dll.lib and object dll.exp

(py35x64_test) e:\Work\Dev\StackOverflow\q053609932>dir /b
code.py
dll.c
dll.exp
dll.lib
dll.obj
dll.so

(py35x64_test) e:\Work\Dev\StackOverflow\q053609932>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32

Calling test0...
From C - [dll.c] (26) - [test0]
test0 returned 42
Calling test1...
From C - [dll.c] (32) - [test1]
From C - [dll.c] (34) - [test1]
Traceback (most recent call last):
  File "code.py", line 30, in <module>
    main()
  File "code.py", line 24, in main
    res = test1_func()
OSError: exception: access violation reading 0x0000000000000010
(py35x64_test) e:\Work\Dev\StackOverflow\q053609932>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32

Calling test0...
From C - [dll.c] (26) - [test0]
test0 returned 42
Calling test1...
From C - [dll.c] (32) - [test1]
From C - [dll.c] (34) - [test1]
Hello world!!!
From C - [dll.c] (36) - [test1]
test1 returned 0