4

Possible Duplicate:
pass callback from python to c++ using boost::python

I have to make a python function as callback of a c++ function.How to do?Where can I find some examples?? I want to use boost.python.

Community
  • 1
  • 1
simon
  • 569
  • 9
  • 20

2 Answers2

3

My approach to this (not the only way)

In C++ I have a class that provides a callback in the following way:

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

and then when I export the class to python (still C++)

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

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

 private:
    PyObject* self; // 1
};

The export of the visitor itself to python

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

And for the export of Mesh you do

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

I always used ... where you can insert any of your arguments.

In python you do something like this

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

  def visit(self):
    # do whatever you want

I also like to make a subclass of ChildrenVisitor that accepts lambda functions, that makes writing visitors in python single lines.


Oh, btw. if you want to call the function at some later point then you would need to change the C++ implementation to something like this

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;
}

And make ChildrenVisitor implement ChildrenVisitorBase.

H. Brandsmeier
  • 957
  • 5
  • 19
0

Your question is answered by this recipe.

If the function you want to have as a callback is already kown at compile time, you should use PyEval_CallObject(...);. If the function must be defined at runtime, use the scheme shown in the recipe to receive the functor pointer.

Soravux
  • 9,653
  • 2
  • 27
  • 25