【问题标题】:Expose C++ member function that has std::function as argument with boost::python使用 boost::python 公开以 std::function 作为参数的 C++ 成员函数
【发布时间】:2016-02-25 19:02:08
【问题描述】:

我有一个包含属性的类,它是一个 std::function。我使用成员函数设置了这个属性的值,所以类看起来像这样:

class ClassName
{    
public:
    void SetCallbackFunction(std::function<void (int i)> callbackFun) {
        m_callbackFunction = callbackFun;
    }

protected:
    std::function<void (int i)> m_callbackFunction;
};

我需要向 Python 公开这个类,当然,我需要公开SetCallbackFunction 函数。 如何使用 boost::python 做到这一点?

【问题讨论】:

  • 您应该添加标签boost-python 以最大限度地提高您的问题到达图书馆专家的机会。 (boost+python!=boost-python)。
  • 感谢您的建议!我添加了 boost-python 标签

标签: python c++ c++11 boost boost-python


【解决方案1】:

由于 Python 对象既可调用又可复制构造,最简单的方法是将辅助函数公开为 SetCallbackFunction,它接受 boost::python::object,然后委托给实际的 SetCallbackFunction 函数:

void ClassName_SetCallbackFunction_aux(ClassName& self, boost::python::object object)
{
  self.SetCallbackFunction(object);
}

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::class_<ClassName>("ClassName", python::init<>())
    .def("set_callback", &ClassName_SetCallbackFunction_aux)
    // ...
    ;
}

ClassName::SetCallbackFunction 直接暴露给 Python 并被调用时,Boost.Python 将在运行时搜索其注册表,以找到 std::function&lt;void (int)&gt; 的 from-Python 转换器。由于这个转换没有被显式注册,Boost.Python 将无法调度函数调用。辅助函数避免了这种运行时转换检查,并从boost::python::object 构造了一个std::function&lt;void (int)&gt; 对象,因为boost::python::object 既是Callable 又是CopyConstructible。


这是一个示例 demonstrating 使用辅助函数将 Python 对象分配为回调:

#include <functional> // std::function
#include <boost/python.hpp>

// Legacy API.
class spam
{
public:
  void SetCallbackFunction(std::function<void (int)> callback)
  {
    callback_ = callback;
  }

  void perform(int x)
  {
    callback_(x);
  }

private:
  std::function<void (int)> callback_;
};

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  // Expose spam.
  python::class_<spam>("Spam", python::init<>())
    // Use an auxiliary function to set Python callbacks.
    .def("set_callback", +[](spam& self, boost::python::object object) {
      self.SetCallbackFunction(object);
    })
    .def("perform", &spam::perform)
    ;
}

互动使用:

>>> import example
>>> called = False
>>> def perform_x(x):
...     assert(42 == x)
...     global called
...     called = True
... 
>>> spam = example.Spam()
>>> spam.set_callback(perform_x)
>>> assert(not called)
>>> spam.perform(42)
>>> assert(called) # Verify callback was invoked
>>> spam.set_callback(lambda: None)
>>> try:
...     spam.perform(42)
...     assert(False) # Verify callback fails (the lambda accepts no args)
... except TypeError:
...     pass
... 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-30
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多