如何使python函数作为c++函数的回调

How to make a python function as callback of a c++ function

本文关键字:函数 c++ 回调 何使 python      更新时间:2023-10-16

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

我必须制作一个python函数作为c++函数的回调。怎么办?我在哪里可以找到一些例子??我想使用boost.python.

我的方法(不是唯一的方法)

在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

您的问题由这个食谱来回答。

如果您想要作为回调的函数在编译时已经被调用,那么您应该使用PyEval_CallObject(...);。如果函数必须在运行时定义,请使用配方中显示的方案来接收函数指针。