3

私は 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 になりません。Foonbits

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]
4

1 に答える 1

0

私は次のことを試みます:

extern "C"
{
    Foo *Foo_new(int nbits)
    {
        Foo *foo = new Foo(nbits);
        printf("Foo_new(%d) => foo=%p\n", nbits, foo);
        return foo;
    }
    void Foo_bar(Foo *foo)
    {
        printf("Foo_bar => foo=%p\n", foo);
        foo->bar();
    }
 }

の値がfoo一致するかどうかを確認します。

また、Boost.Pythonを調べて、C++オブジェクトのPythonバインディングの作成を簡素化することもできます。

于 2012-12-06T23:21:30.783 に答える