我对 python ctypes 模块并不陌生,但这是我第一次尝试在一个代码中结合 C++、C 和 Python。在将 ctypes 与 Python 和 C++ 一起使用时,我的问题似乎与Seg 错误非常相似,但是我似乎无法以相同的方式解决问题。
我有一个简单的 C++ 文件,名为Header.cpp
:
#include <iostream>
class Foo{
public:
int nbits;
Foo(int nb){nbits = nb;}
void bar(){ std::cout << nbits << std::endl; }
};
extern "C" {
Foo *Foo_new(int nbits){ return new Foo(nbits); }
void Foo_bar(Foo *foo){ foo->bar(); }
}
我使用以下方法编译到共享库:
g++ -c Header.cpp -fPIC -o Header.o
g++ -shared -fPIC -o libHeader.so Header.o
和一个简单的 Python 包装器,称为test.py
:
import ctypes as C
lib = C.CDLL('./libHeader.so')
class Foo(object):
def __init__(self,nbits):
self.nbits = C.c_int(nbits)
self.obj = lib.Foo_new(self.nbits)
def bar(self):
lib.Foo_bar(self.obj)
def main():
f = Foo(32)
f.bar()
if __name__ == "__main__":
main()
我希望当我调用 test.py 时,我应该将数字 32 打印到屏幕上。但是,我得到的只是一个分段错误。如果我更改构造函数以返回堆栈上的类实例(即没有new
调用),然后传递对象,程序将按预期执行。此外,如果我更改类中的bar
方法以Foo
使其不使用该nbits
成员,则程序不会出现段错误。
我对 C++ 的了解有限,但是我可以在 C 和 C++ 中按预期实现这个函数,但在 Python 中却不行,这有点令人困惑。任何帮助将不胜感激。
更新:感谢以下评论之一,问题已解决。在这种情况下,需要为 C 函数显式声明 restype 和 argtypes。即以下被添加到python代码中:
lib.Foo_new.restype = C.c_void_p
lib.Foo_new.argtypes = [C.c_int32]
lib.Foo_bar.restype = None
lib.Foo_bar.argtypes = [C.c_void_p]