可能重复: 使用boost :: python将回调从python传递给c ++
我必须将python函数作为c ++函数的回调。如何做?在哪里可以找到一些例子? 我想使用boost.python。
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.
最满意答案
我的方法(不是唯一的方法)
在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我还想创建一个接受lambda函数的ChildrenVisitor的子类,这使得访问者可以用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 。
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 wantI 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.
更多推荐
发布评论