Python C API-使用比较函数导致';分段错误';
我目前正在学习用C编写Python扩展,一切似乎都进行得很顺利。然而,当我尝试使用比较函数时,它们都会导致分段错误。例如:Python C API-使用比较函数导致';分段错误';,python,c,api,Python,C,Api,我目前正在学习用C编写Python扩展,一切似乎都进行得很顺利。然而,当我尝试使用比较函数时,它们都会导致分段错误。例如: #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", res
#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\u 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)
编辑2:
“test()”函数中没有Python解释器的初始化(没有Py_初始化调用) PyInt_FromLong()返回指向内部数组的指针,该数组在您的示例中未初始化。因此,您得到一些无效指针并将其传递给Py_Compare()函数会使解释器崩溃 有关初始化的详细信息,请参见此处: 至少尝试在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;
}
#包括
typedef int(*fcn)();
int main()
{
void*dll=dlopen(“libtest.so”,RTLD_-LAZY);
/*这里有错误检查*/
fcn测试=(fcn)dlsym(dll,“测试”);
Test();
dclose(dll);
返回0;
}
编辑2:
如果“result=-1”出现在基于python的应用程序中,则错误出现在ctypes中,而不是libtest中。因此,在“test()”函数中没有python解释器的初始化(没有Py\u初始化调用) PyInt_FromLong()返回指向内部数组的指针,该数组在您的示例中未初始化。因此,您得到一些无效指针并将其传递给Py_Compare()函数会使解释器崩溃 有关初始化的详细信息,请参见此处: 至少尝试在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;
}
#包括
typedef int(*fcn)();
int main()
{
void*dll=dlopen(“libtest.so”,RTLD_-LAZY);
/*这里有错误检查*/
fcn测试=(fcn)dlsym(dll,“测试”);
Test();
dclose(dll);
返回0;
}
编辑2:
如果“result=-1”出现在基于python的应用程序中,则错误出现在ctypes中,而不是libtest中。因此。提供一个显示问题的最小完整示例。您是如何初始化python的?您使用多线程吗?你在检查错误吗?python仍然是初始化的还是您破坏了它?您是否尝试重新加载解释器?请显示完整的最小程序。@Arafangion我试过使用python脚本,也试过使用解释器,同样的问题。但我没有检查错误。我真的不知道该检查什么,对不起,我还是个初学者。如果你想写一个C扩展,为什么要使用
ctypes
?我发现一开始就比较容易。我不是真的想写一个扩展,只是想学习如何做。像这样使用ctypes是错误的吗?请提供一个最小的、完整的示例来说明这个问题。您是如何初始化python的?您使用多线程吗?你在检查错误吗?python仍然是初始化的还是您破坏了它?您是否尝试重新加载解释器?请显示完整的最小程序。@Arafangion我试过使用python脚本,也试过使用解释器,同样的问题。但我没有检查错误。我真的不知道该检查什么,对不起,我还是个初学者。如果你想写一个C扩展,为什么要使用ctypes
?我发现一开始就比较容易。我不是真的想写一个扩展,只是想学习如何做。像这样使用ctypes错误吗?谢谢你的回答,但是使用Py_Initialize()没有任何区别。我将不得不尝试不使用其他人建议的ctypes。您可以添加“python config--ldflags”和“python config--cflags”的输出吗?我在问题中添加了它们。谢谢。增加了C测试。也许你可以尝试一下,然后转储GDB的输出,看看它为什么会崩溃?再次感谢你,我还是个初学者,现在用GDB调试东西对我来说是不可能的。然而,我试着运行你的C测试,但一开始它不起作用,在搜索了一段时间后,我在我的共享库中使用了带有gcc的-lpthread
(不知道为什么),然后你的测试程序使用了它,但是带有ctypes的python仍然给出了相同的行为。谢谢你的回答,但是使用Py_Initialize()没什么不同。我将不得不尝试不使用其他人建议的ctypes。您可以添加“python config--ldflags”和“python config--cflags”的输出吗?我在问题中添加了它们。谢谢。增加了C测试。也许你可以尝试一下,然后转储GDB的输出,看看它为什么会崩溃?再次感谢你,我还是个初学者,现在用GDB调试东西对我来说是不可能的。然而,我试过了