4

可能重复:
使用 boost::python 将回调从 python 传递到 c++

我必须制作一个python函数作为c++函数的回调。怎么办?在哪里可以找到一些例子?我想使用 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接受 lambda 函数的子类,这使得用 python 单行编写访问者。


哦,顺便说一句。如果您想稍后调用该函数,那么您需要将 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 回答