我目前正在尝试学习用C编写Python扩展,一切似乎进展顺利。但是,当我尝试使用比较功能时,它们都会导致Segmentaion故障。例如:
#include "Python.h"
int test(void) {
int result;
printf("Before compare...\n");
result = PyObject_Compare(PyInt_FromLong(1), PyInt_FromLong(3));
printf("result= %d\n", result);
return 0;
}
从Python执行test()
(我使用了ctypes)给出了以下输出:
Before compare...
Segmentation fault
对于其他比较函数,我发生这种情况,例如:PyObject_cmp
...等
感谢任何帮助,谢谢。
我首先将文件(test.c)编译为共享库:
$> python-config --cflags
-I/usr/include/python2.7 -I/usr/include/python2.7 -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes
$> python-config --ldflags
-L/usr/lib/python2.7/config -lpthread -ldl -lutil -lm -lpython2.7 -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions
$> gcc -c $(python-config --cflags) ./test.c -o test.o
$> gcc -shared ./test.o $(python-config --ldflags) -o libtest.so
然后我从Python开始使用这个函数:
import ctypes
testlib = ctypes.CDLL('./libtest.so')
testlib.test()
使用Viktor提供的测试
$> gcc -o dlltest test.c -ldl
$> gdb dlltest
(gdb) run
Starting program: dlltest
[Thread debugging using libthread_db enabled]
Cannot find new threads: generic error
(gdb)
所以我这样做了:
$> LD_PRELOAD=libpthread-2.13.so gdb dlltest
(gdb) run
Starting program: dlltest
[Thread debugging using libthread_db enabled]
Before compare...
result= -1
[Inferior 1 (process 3274) exited normally]
(gdb)
>$ gdb --args python frompython.py
(gdb) run
Starting program: /usr/bin/python frompython.py
[Thread debugging using libthread_db enabled]
Before compare...
Program received signal SIGSEGV, Segmentation fault.
0x080a855b in PyObject_Compare ()
(gdb) backtrace
#0 0x080a855b in PyObject_Compare ()
#1 0x005225d8 in test () at ./testmod.c:29
#2 0x005181ca in ffi_call_SYSV ()
from /usr/lib/python2.7/lib-dynload/_ctypes.so
#3 0x00517eff in ffi_call () from /usr/lib/python2.7/lib-dynload/_ctypes.so
#4 0x00510312 in _ctypes_callproc ()
from /usr/lib/python2.7/lib-dynload/_ctypes.so
#5 0x0050788d in ?? () from /usr/lib/python2.7/lib-dynload/_ctypes.so
#6 0x0805dc31 in PyObject_Call ()
#7 0x080f81c1 in PyEval_EvalFrameEx ()
#8 0x080fd804 in PyEval_EvalCodeEx ()
#9 0x080fe177 in PyEval_EvalCode ()
#10 0x0811acd0 in ?? ()
#11 0x0811b8e9 in PyRun_FileExFlags ()
#12 0x0811c4cc in PyRun_SimpleFileExFlags ()
#13 0x0812c7c6 in Py_Main ()
#14 0x0805da0b in main ()
(gdb)
答案 0 :(得分:5)
在'test()'函数中没有初始化Python的解释器(没有Py_Initialize调用)。
PyInt_FromLong()返回一个指向内部数组的指针,在你的情况下它是未初始化的。所以你得到一些无效指针并将它传递给Py_Compare()函数会使解释器崩溃。
有关初始化的详细信息,请参阅此处: http://docs.python.org/c-api/init.html#initializing-and-finalizing-the-interpreter
至少尝试在test()函数的开头添加“Py_Initialize()”调用。
编辑:
有趣的是,如果你使用这个编程从C运行libtest.test,那么GDB的堆栈跟踪是什么:
#include <dlfcn.h>
typedef int (*fcn)();
int main()
{
void* dll = dlopen("libtest.so", RTLD_LAZY);
/* dlerror checks here */
fcn Test = (fcn)dlsym(dll, "test");
Test();
dclose(dll);
return 0;
}
EDIT2:
编译测试(gcc -o dlltest test.c -ldl)
运行“gdb dlltest”
在gdb提示符下键入命令“run”
查看是否崩溃
如果是,请在gdb的提示符下键入backtrace。
EDIT3:
目前还不清楚坠机的位置。尝试添加“fflush(stdout);”在每次printf()调用之后,确保打印错误。
如果基于python的应用程序中出现“result = -1”,则错误在ctypes中,而不在libtest.so中。