通过Boost Python将Python函数转换为C ++,用作回调

时间:2018-06-06 16:49:58

标签: python c++ boost boost-python

一般来说,通过Boost-Python传递Python函数的推荐方法是什么,以便以后在C ++代码中使用(即作为C ++对象中的回调)?

更具体地说,我有一个C ++类FooCPP,我通过Boost-Python成功地将其暴露给了Python;用户与运行C ++对应的Python类Foo进行交互。举例:

# Foo.py

from foo_base import FooBase

class Foo(FooBase):
    ...

def callback(val=42.):
    return val

foo = Foo()
foo.run(callback)

Boost Python绑定:

// foo_bindings.cpp

#include "foo.hpp"
#include <boost/python.hpp>

namespace bp =  boost::python;

FooPython::Run(const bp::object& py_callback)
    // TODO: Do something with the python callback to make it a C++ function!
    std::function<double(double)> cpp_callback;
    FooCPP::Run(cpp_callback);
)

BOOST_PYTHON_MODULE(foo_base){
    bp::class_<FooPython>("FooBase")
    .def("run", &FooPython::Run)
    ;
}

那么如何解决foo_bindings.cpp中的TODO注释?

我已经完成了许多相关的SO问题 - 例如pass python function to boost csending py function as boost function arg - 我熟悉Boost-Python docs,但没有找到一个好的解决方案/解释。提前谢谢!

注:C ++ 11,boost v1.58.0,ubuntu 16.04

更新

我可能刚刚找到了一个解决方案,我可以在foo_bindings.cpp中实现一个仿函数,例如,

struct PythonCallback {
public:
    PythonCallback(bp::object cb_func) : cb_func_(cb_func) {}
    double operator() (const double& val) {
        // Call the callback function in python
        return cb_func_(val);
    }
private:
    bp::object cb_func_;
};

但那么FooCPP::Run签名应该是什么?即为传递的cpp_callback定义了什么类型?

此回调函数需要更改BOOST_PYTHON_MODULE代码吗?

1 个答案:

答案 0 :(得分:1)

在foo_bindings.cpp中实现一个仿函数,其中使用call调用回调:

#include <boost/python.hpp>
#include <boost/python/call.hpp>

struct PythonCallback : {
public:
    PythonCallback(PyObject* func) : cb_(func) {}
    double operator() (const double& value) {
        // Call the callback function in python
        return boost::python::call<double>(cb_, value);
    }
private:
    PyObject* cb_;
};