1

C++ アプリケーションに Python を埋め込んでいます。C++ は python を呼び出し、それを引数として C++ オブジェクトに渡します。そのオブジェクトにはいくつかの仮想関数があり、派生クラスの基本クラスになることができます。boost::python にそれが仮想関数であることを理解させるにはどうすればよいですか?

次の点を考慮してください:
C++ の場合:

class Base {
public:
  virtual void func();
}

class Derived {
public:
  virtual void func();
}

BOOST_PYTHON_MODULE(module_api) {
  class_<Base>("Base")
    .def("func", &Base::func);  // ?? what should I put here?
}

int main() {
  //... initialization
  Derived derived;
  main_namespace["pyentry"](&derived);
}

パイソンで:

def pyentry(baseref):
  baseref.func()    # here I want Derived::func() to be called

ここで何が間違っていますか?

4

1 に答える 1

2

ここでの問題は、Boost.Python が派生クラス オブジェクトをディープ コピーし、それを Python に変換するときにベース オブジェクトにスライスすることです。Python でオーバーライドする必要がない限り、Boost.Python に関数が仮想であることを伝える必要はまったくありません (そうしないように思えます)。

安全のためにそのコピーを行っています。Python が指定したオブジェクトが C++ によって削除されないことを確認していますが、Python はまだそのオブジェクトへの参照を持っています。そして、それをスライスしていBaseます - 私が思うに - それは について何も知らないからDerivedです。

これを修正するには、次の 2 つの方法が考えられます。

  • の簡単なラッパーを提供しますDerived。Boost.Python は、Python に変換するときにそれをコピーしますが、そうするBaseときにもうスライスしません。

  • (経由で) のshared_ptr変換を登録し、でインスタンスを作成し、それを引数として Python 関数に渡します。これで Boost.Python は、Python オブジェクトが存在する間は C++ オブジェクトを削除できないことを認識します。これは、Python ラッパーが C++ オブジェクトへの参照を保持しているためです。Baseregister_ptr_to_python< boost::shared_ptr<Base> >()Derivedshared_ptrshared_ptr

于 2012-05-12T23:23:55.767 に答える