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

Posted

技术标签:

【中文标题】通过 Boost Python 将 Python 函数转换为 C++,用作回调【英文标题】:Convert Python function to C++, via Boost Python, for use as a callback 【发布时间】:2018-06-06 16:49:58 【问题描述】:

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

更具体地说,我有一个 C++ 类 FooCPP,我已经通过 Boost-Python 成功地接触了 Python;用户与 Python 类 Foo 交互,该类在后台运行 C++ 对应项。人为的例子:

# 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 c 和 sending 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 签名应该是什么? IE。传入的cpp_callback 定义了什么类型?

对于这个回调函子,BOOST_PYTHON_MODULE 代码是否需要更改?

【问题讨论】:

您是否只需要为单个函数类型(例如:double(double))或更通用的类型执行此操作? @SeanMcAllister 如果有一个更通用的回调函数的解决方案,它接受其他参数 - 例如callback(x, y=42., z=True) -- 很高兴看到。 【参考方案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_;
;

【讨论】:

以上是关于通过 Boost Python 将 Python 函数转换为 C++,用作回调的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Boost.Python 从 python 文件中导入函数

boost::python - C++ 调用 Python 调用 C++

将 boost::python::numpy::ndarray 作为 boost::python 函数的(默认与否)参数传递?

boost-python:如何提供自定义构造函数包装函数?

扩展通过 Boost.Python 公开的虚拟 C++ 类

使用 Boost.Python 将 Python 转换为 C++ 函数