私は python ctypes モジュールをよく知っていますが、C++、C、および Python をすべて 1 つのコードにまとめようとするのはこれが初めての試みです。Python および C++ で ctypes を使用する場合、私の問題は Seg fault と非常に似ているようですが、同じ方法で問題を解決できなかったようです。
という単純な 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
メソッドを変更すると、プログラムは seg fault になりません。Foo
nbits
C++ についての理解は限られていますが、この関数を C と C++ では期待どおりに作成できますが、Python では作成できないという事実は少し混乱を招きます。どんな助けでも大歓迎です。
更新: 以下のコメントの 1 つにより、問題は解決されました。この場合、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]