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.

4
  • Does that mean you want to call a python function from a C++ function? Commented Sep 2, 2012 at 14:37
  • you make a c++ function as callback of a c++ function and call the python function inside it Commented Sep 2, 2012 at 14:39
  • @David Robinson: the poster explicitely asked for a boost-python solution, so I think this is a valid question. Commented Sep 4, 2012 at 8:40
  • @cideous: which poster? Both this question and the original ask explicitly for boost::python Commented Sep 4, 2012 at 12:39

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.