1

Boost.Python を使用して、この C++ クラスを公開しようとしています。

class VAlgorithm {
public:

  VAlgorithm(const char *name);

  virtual ~VAlgorithm();

  virtual bool Initialize() = 0;
  virtual bool Process() = 0;
  virtual bool Finalize() = 0;

  virtual const char *GetName() const; // Default implementation in cpp file
}

私の最終的な目標は、Python シェルで VALgorithm の子を Python クラスとして定義することです。この例に従って、コールバック クラスを定義しました。

class VAlgorithm_callback: public VAlgorithm {
public:
  VAlgorithm_callback(PyObject *p, const char *name) :
      self(p), VAlgorithm(name) {
  }
  const char * GetName() const {
    return call_method<const char *>(self, "GetName");
  }

  static const char * GetName_default(const VAlgorithm& self_) {
    return self_.VAlgorithm::GetName();
  }

private:
  PyObject *self;
};

現在、クラス自体と GetName() メソッドのみを公開しています。これは仮想クラスであるため、次のコードを BOOST_PYTHON_MODULE 内に配置しました。

class_<VAlgorithm, VAlgorithm_callback, boost::noncopyable>("VAlgorithm", no_init) //
  .def("GetName", &VAlgorithm_callback::GetName_default); //

これをコンパイルして、Python シェルにモジュールをロードできます。次に、子クラスを定義して、C++ コードで定義されている GetName() の既定の実装を呼び出します。

>>> class ConcAlg1(VAlgorithm):
...   pass
... 
>>> c1 = ConcAlg1("c1")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: This class cannot be instantiated from Python
>>> class ConcAlg2(VAlgorithm):
...   def __init__(self, name):
...     pass
... 
>>> c2 = ConcAlg2("c2")
>>> c2.GetName()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    VAlgorithm.GetName(ConcAlg2)
did not match C++ signature:
    GetName(VAlgorithm)
>>> class ConcAlg3(VAlgorithm):
...   def __init__(self, name):
...     super(ConcAlg3, self).__init__(self, name)
... 
>>> c3 = ConcAlg3("c3")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
RuntimeError: This class cannot be instantiated from Python

私は専門家ではありません (これらの問題に初めて直面しただけです) が、ConcAlg1 と ConcAlg3 が VAlgorithm オブジェクトをインスタンス化しようとして、VALgorithm を公開するときに使用される no_init パラメーターが原因で失敗するように思えます (省略できないか、コードはコンパイルされません)、ConcAlg2 は GetName() を呼び出すことができません。これは、どういうわけか VAlgorithm の子として認識されないためです。私は些細なことをしているに違いありませんが、何が原因かわかりません (私は Boost.Python と拡張機能の初心者です)。誰でも私を助けてもらえますか?ありがとう

4

2 に答える 2

0

私は解決策を見つけたと思います。私が質問で引用した例と、ここにあるブーストのドキュメントを見て、問題は、コールバッククラスがBoost.Pythonによってラップされている実際のクラスであり、具象クラスでなければならないことであることがわかりました。そこで、不足している純粋仮想メソッドを実装しました。

class VAlgorithm_callback: public VAlgorithm {
public:
  VAlgorithm_callback(PyObject *p, const char *name) :
      self(p), VAlgorithm(name) {
  }

  virtual bool Initialize() {
    return call_method<bool>(self, "Initialize");
  }
  virtual bool Process() {
    return call_method<bool>(self, "Process");
  }
  virtual bool Finalize() {
    return call_method<bool>(self, "Finalize");
  }

  const char * GetName() const {
    return call_method<const char *>(self, "GetName");
  }

// Supplies the default implementation of GetName
  static const char * GetName_default(const VAlgorithm& self_) {
    return self_.VAlgorithm::GetName();
  }

private:
  PyObject *self;
};

また、ラッパーを次のように変更しました。

class_<VAlgorithm, boost::shared_ptr<VAlgorithm_callback>, boost::noncopyable ("VAlgorithm", init<const char *>()) //
 .def("Initialize", &VAlgorithm_callback::Initialize)
 .def("Process", &VAlgorithm_callback::Process)
 .def("Finalize", &VAlgorithm_callback::Finalize)
 .def("GetName", &VAlgorithm_callback::GetName_default);

これで、Pythonで子クラスを定義し、デフォルトのGetName()メソッドを呼び出すことができます。

>>> class ConcAlg(VAlgorithm):
...   pass
... 
>>> c = ConcAlg("c")
>>> c.GetName()
'c'
>>>
于 2012-09-06T15:14:33.450 に答える
0

私はこれと非常によく似たことをしました。コメントで見つけたものをフォローしてみませんか?

PythonでVAlgorithmから派生するクラスのインスタンスを作成する場合、それを表すためにVAlgorithm_callbackをC++でインスタンス化する必要があります。BOOST_PYTHON_MODULEでコンストラクターを宣言しないと、不可能です。

例で行った方法で実行しても問題ありません。

class_<VAlgorithm, VAlgorithm_callback, boost::noncopyable>("VAlgorithm", init<std::string>())

子クラスのinitを定義するときは、次の構文を使用して親コンストラクターを呼び出すことができます(ただし、コードも機能する可能性があります。これは私と同じ方法です)。使用した例では、 initを定義していないため、代わりに親が呼び出されます。

class ConcAlg3(VAlgorithm):
    def __init__(self, name):
    VAlgorithm.__init__(self, name)
于 2012-09-06T15:16:15.687 に答える