Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.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
Python到C到Python调用流导致分段错误_Python_C - Fatal编程技术网

Python到C到Python调用流导致分段错误

Python到C到Python调用流导致分段错误,python,c,Python,C,我需要从python调用C函数,而C函数反过来调用python方法。例如:test.py调用hello.C中的C函数,该C函数调用hello.py中的方法。 在这种情况下,当我尝试在C函数中加载.py模块(使用PyImport\u ImportModule)时,导致分段错误(内核转储)。 您能否帮助调试/解决此问题的根本原因?让我知道,如果我遗漏了什么,或者有没有其他方法让它工作 py如下所示,它使用ctypes并调用C函数 import time import ctypes def _run

我需要从python调用C函数,而C函数反过来调用python方法。例如:test.py调用hello.C中的C函数,该C函数调用hello.py中的方法。 在这种情况下,当我尝试在C函数中加载.py模块(使用PyImport\u ImportModule)时,导致分段错误(内核转储)。
您能否帮助调试/解决此问题的根本原因?让我知道,如果我遗漏了什么,或者有没有其他方法让它工作

py如下所示,它使用ctypes并调用C函数

import time
import ctypes

def _run():
    _hello = ctypes.CDLL('./hello.so')
    result = _hello.hello_main()
    time.sleep(10)

if __name__ == "__main__" :
    _run()
c如下所示,它正在加载hello py模块

#include <Python.h>

int hello_main()
{
     PyObject *pModule = NULL;
     PyObject *pFunc   = NULL;

     Py_Initialize();
     printf("Import Py module\n");
     pModule = PyImport_ImportModule("hello");
     if (pModule == NULL) {
         printf("Py module import fail\n");
         return 0;
     }

     pFunc = PyObject_GetAttrString(pModule, "Hello");
     if (pFunc == NULL) {
         printf("Py module get attr fail \n");
         return 0;
     }
     PyEval_CallObject(pFunc, NULL);

     Py_Finalize();

     return 0;
}
C代码编译为共享库,如下所示:

[host]# gcc -g -o hello.so hello.c -shared -fPIC -I/usr/include/python2.7 -L/usr/lib/python2.7 -lpython2.7
当我运行test.py时,我得到了分段错误

[host]# python test.py 
Import Py module
Segmentation fault (core dumped)
以下是核心的回溯:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b116a0 in threadstate_getframe () from /lib64/libpython2.7.so.1.0
(gdb) bt
#0  0x00007ffff7b116a0 in threadstate_getframe ()
   from /lib64/libpython2.7.so.1.0
#1  0x00007ffff7aef5c9 in PyEval_GetGlobals () from /lib64/libpython2.7.so.1.0
#2  0x00007ffff7b0b222 in PyImport_Import () from /lib64/libpython2.7.so.1.0
#3  0x00007ffff7b0b48a in PyImport_ImportModule ()
   from /lib64/libpython2.7.so.1.0
#4  0x00007fffefdcc980 in hello_main () at hello.c:15
#5  0x00007ffff01dcdcc in ffi_call_unix64 () from /lib64/libffi.so.6
#6  0x00007ffff01dc6f5 in ffi_call () from /lib64/libffi.so.6
#7  0x00007ffff03efc8b in _ctypes_callproc ()
   from /usr/lib64/python2.7/lib-dynload/_ctypes.so
#8  0x00007ffff03e9a85 in PyCFuncPtr_call ()
   from /usr/lib64/python2.7/lib-dynload/_ctypes.so
#9  0x00007ffff7a5d8e3 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#10 0x00007ffff7af2036 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#11 0x00007ffff7af64bd in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#12 0x00007ffff7af8e3d in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#13 0x00007ffff7af8f42 in PyEval_EvalCode () from /lib64/libpython2.7.so.1.0
#14 0x00007ffff7b1237f in run_mod () from /lib64/libpython2.7.so.1.0
#15 0x00007ffff7b1353e in PyRun_FileExFlags () from /lib64/libpython2.7.so.1.0
#16 0x00007ffff7b147c9 in PyRun_SimpleFileExFlags ()
   from /lib64/libpython2.7.so.1.0
#17 0x00007ffff7b2591f in Py_Main () from /lib64/libpython2.7.so.1.0
---Type <return> to continue, or q <return> to quit---
#18 0x00007ffff6d4db35 in __libc_start_main () from /lib64/libc.so.6
#19 0x0000000000400721 in _start ()
(gdb) quit
如中所述

在Py_Initialize()之后添加以下代码,修复崩溃问题

PyGILState_STATE d_gstate;
d_gstate = PyGILState_Ensure();

谢谢你的帮助。

你检查过被丢弃的堆芯了吗?哪个函数导致了它,在哪个文件中,在哪一行?调用的
CDLL
没有保存GIL。再加上这种疯狂,你正试图重新初始化解释器。为什么不能给C函数一个ctypes回调函数来回调Python呢?ctypes将为您处理重新获取和发布GIL的详细信息。谢谢回复。要求是-我们有一些用C和python编写的特性代码。C为该特性提供了API。然后,我们有另一个Python应用程序,我们希望通过调用C API(inturn在内部调用Python模块)来使用现有功能。我们没有太多的灵活性来重写/修改现有的C API代码,但是只需要找到胶水来使用python应用程序中的C API。有没有办法让这一切顺利进行?非常感谢您的帮助。对于gbd,下面是回溯。我觉得您需要将预先存在的C API封装在C扩展中。C扩展中的函数可用于将Python变量转换为C变量、调用C API并将值返回给Python。我这样做是为了学术界和我的职业。阅读更多。
PyEval_GetGlobals(void)
 - PyEval_GetFrame();
     - PyThreadState *tstate = PyThreadState_GET();
     - return _PyThreadState_GetFrame(tstate);      ==> Crashing here
PyGILState_STATE d_gstate;
d_gstate = PyGILState_Ensure();