4

重複の可能性:
boost::python を使用して Python から C++ にコールバックを渡す

C++ 関数のコールバックとして Python 関数を作成する必要があります。方法は?例はどこにありますか?? boost.python を使いたい。

4

2 に答える 2

3

これに対する私のアプローチ(唯一の方法ではありません)

C++ では、次の方法でコールバックを提供するクラスがあります。

struct Mesh {
 template<class Visitor>
  void visitChildren(Visitor& v)
  {
     [...]
     v.visit([...])
  }
}

そして、クラスを python (まだ C++) にエクスポートすると

struct ChildrenVisitor 
{
   ChildrenVisitor(PyObject* self)
        : self(self) 
   {}

  void visit( /* .... */ )
  {
    call_method<void>(self, "visit" /*, [...] */ );
  }

 private:
    PyObject* self; // 1
};

ビジター自体の Python へのエクスポート

typedef ChildrenVisitor ClassT;
class_<ClassT, boost::noncopyable >("ChildrenVisitor",
    init<PyObject*>() );

Meshそして、あなたの輸出のために

.def("visitChildren", &Mesh::template visitChildren<ChildrenVisitor> )

私は常に...、引数を挿入できる場所を使用しました。

Pythonでは、このようなことをします

class MyVisitor(ChildrenVisitor): 
  def __init__(self):
    ChildrenVisitor.__init__(self,self)

  def visit(self):
    # do whatever you want

ChildrenVisitorまた、ラムダ関数を受け入れるのサブクラスを作成することも好きです。これにより、ビジターを Python の 1 行で記述できるようになります。


ああ、ところで。後で関数を呼び出したい場合は、C++ 実装を次のように変更する必要があります。

struct ChildrenVisitorBase 
{
  virtual void visit( /* .... */ ) = 0;
};

struct Mesh {
  void registerCallback(shared_ptr<ChildrenVisitorBase> v)
  {
     visitors.push_back(v)
  }

  void doSomeWork() {
    // ...
    for(int i=0; i < visitors.size(); ++i)
      visitors[i]->visit( /* ... */ )
  }

  std::vector<  shared_ptr<ChildrenVisitorBase> > visitors;
}

そしてChildrenVisitor実装しChildrenVisitorBaseます。

于 2012-09-04T08:33:18.723 に答える
0

あなたの質問はこのレシピで答えられます。

コールバックとして使用したい関数がコンパイル時にすでにわかっている場合は、PyEval_CallObject(...);. 実行時に関数を定義する必要がある場合は、レシピに示されているスキームを使用して、ファンクター ポインターを受け取ります。

于 2012-09-02T17:28:16.510 に答える