使用boost :: python公开具有std :: function作为参数的C ++成员函数 [英] Expose C++ member function that has std::function as argument with boost::python

查看:145
本文介绍了使用boost :: python公开具有std :: function作为参数的C ++成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含一个属性的类,该属性是std :: function.我使用成员函数设置了此属性的值,因此该类如下所示:

I have a class that contains an attribute which is a std::function. I set the value of this attribute using a member function, so the class looks like this:

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做到这一点?

I need to expose this class to Python and, of course, I need to expose the SetCallbackFunction function. How can I do this with boost::python?

推荐答案

由于Python对象既是Callable对象又是CopyConstructible对象,所以最简单的方法是将辅助函数公开为SetCallbackFunction并接受boost::python::object,然后将其委托给实际的SetCallbackFunction函数:

As Python objects are both Callable and CopyConstructible, the simplest approach is to expose an auxiliary function as SetCallbackFunction that accepts a boost::python::object, then delegates to the actual SetCallbackFunction function:

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<void (int)>的from-Python转换器.由于尚未明确注册此转换,因此Boost.Python将无法分派函数调用.辅助功能避免了此运行时转换检查,并从boost::python::object构造了std::function<void (int)>对象,因为boost::python::object既是Callable的又是CopyConstructible的.

When ClassName::SetCallbackFunction is directly exposed to Python and invoked, Boost.Python will search its registry at runtime to locate a from-Python converter for std::function<void (int)>. As this conversion has not been explicitly registered, Boost.Python will fail to dispatch the function call. The auxiliary function avoids this runtime conversion check and constructs a std::function<void (int)> object from a boost::python::object, as the boost::python::object is both Callable and CopyConstructible.

下面是一个示例演示,该示例使用辅助函数将Python对象分配为回调:

Here is an example demonstrating using an auxiliary function to assign Python objects as callbacks:

#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
... 

这篇关于使用boost :: python公开具有std :: function作为参数的C ++成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆