这是我的C代码,我用它创建了一个共享库。当我在Python中加载共享库并执行下面的Python代码时,我崩溃了。为什么?
extern "C" {
PyObject* foo2(char* b)
{
return Py_BuildValue("s", b);
}
}
以下是我在Python中所做的事情:
from ctypes import *
d = cdll.LoadLibrary('./foo.so')
d.foo2.restype = c_char_p
v = d.foo2('hello world')
print pythonapi.PyString_Size(v)
如果有帮助,我在Python2.6。
答案 0 :(得分:9)
你的问题是你在说谎的回报类型:
d.foo2.restype = c_char_p
实际的返回类型是PyObject *
。但是ctypes
会看到c_char_p
,将PyObject *
投射到char *
,然后尝试将char *
转换为{{1}的字符串这将会读取谁知道什么是任意字节,直到它击中NUL字符。
指定PyString_FromString
的方式是使用py_object
。
此外,您可能想要设置PyObject *
。而这一次, 是argtype
:
c_char_p
但是,正如interjay在评论中指出的那样,构建一个使用Python C API然后通过d = cdll.LoadLibrary('./foo.so')
d.foo2.argtypes = [c_char_p]
d.foo2.restype = py_object
调用它的C库有点愚蠢。这偶尔有用,但通常情况下,解决方案是完成构建C扩展模块而不是完成80%的工作而没有任何好处......
答案 1 :(得分:4)
您告诉cdll
该函数返回char*
但实际上它返回PyObject*
。这两者需要达成一致。