您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

在Boost Python中公开C ++接口

在Boost Python中公开C ++接口

不能以这种方式将抽象C 类公开给Boost.Python。Boost.Python 教程提供了有关如何公开纯虚 函数的示例。简而言之,当使用修饰装饰 方法boost::python::pure_virtual,需要创建包装器类型,以允许C 对虚拟函数进行多态解析,并且虚拟函数实现将在Python对象的层次结构中委派多态解析函数

struct BaseWrap : Base, boost::python::wrapper<Base>
{
  int foo()
  {
    return this->get_override("foo")();
  }
};

...

boost::python::class_<BaseWrap>("Base", ...)
  .def("foo", boost::python::pure_virtual(&Base::foo))
  ;

有关详细信息,当通过公开类型时boost::python::class_HeldType认为公开的类型,并且HeldType在Python对象中构造。该class_文档指出:

模板参数:

因此,该操作boost::python::class_<Base>将失败,因为T = BaseandHeldType = Base和Boost.Python将尝试将对象实例HeldType化为表示实例的Python对象Base。此实例化将失败,就像Base抽象类一样。

这是显示BaseWrap类使用的完整示例。

#include <boost/python.hpp>

struct Base
{
  virtual int foo() = 0;
  virtual ~Base() {}
};

struct Derived : public Base
{
  virtual int foo()
  {
    return 42;
  }
};

Base* get_base()
{
  return new Derived;
}

namespace python = boost::python;

/// @brief Wrapper that will provide a non-abstract type for Base.
struct BaseWrap : Base, python::wrapper<Base>
{
  BaseWrap() {}

  BaseWrap(const Base& rhs)
    : Base(rhs)
  {}

  int foo()
  {
    return this->get_override("foo")();
  }
};

BOOST_PYTHON_MODULE(example)
{
  python::class_<BaseWrap>("Base")
    .def("foo", python::pure_virtual(&Base::foo));
    ;

  python::def("get_base", &get_base,
              python::return_value_policy<python::manage_new_object>());
}

及其用法

>>> import example
>>> class Spam(example.Base):
...     pass
... 
>>> Spam().foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: Pure virtual function called
>>> class Egg(example.Base):
...     def foo(self):
...         return 100
... 
>>> e = Egg()
>>> e.foo()
100
>>> d = example.get_base()
>>> d.foo()
42

可以通过不使用认初始化器(boost::python::no_init)和不可复制(boost::noncopyable)进行公开来在Boost.Python中公开一个抽象类。缺少初始化器会阻止从其派生Python类型,从而有效地防止覆盖。另外,Base::foo()在C ++中由实现的实现细节Derived是无关紧要的。如果Python根本不了解某个foo()方法,请省略通过公开它def()

#include <boost/python.hpp>

struct Base
{
  virtual int foo() = 0;
  virtual ~Base() {}
};

struct Derived
  : public Base
{
  virtual int foo()
  {
    return 42;
  }
};

struct OtherDerived
  : public Base
{
  virtual int foo()
  {
    return 24;
  }
};

Base* get_base()
{
  return new Derived;
}

Base* get_other_base()
{
  return new OtherDerived;
}

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::class_<Base, boost::noncopyable>("Base", python::no_init)
    ;

  python::class_<Derived, python::bases<Base> >("Derived", python::no_init)
    .def("foo", &Base::foo)
    ;

  python::class_<OtherDerived, python::bases<Base> >(
      "OtherDerived", python::no_init)
    ;

  python::def("get_base", &get_base,
              python::return_value_policy<python::manage_new_object>());

  python::def("get_other_base", &get_other_base,
              python::return_value_policy<python::manage_new_object>());
}

互动用法

>>> import example
>>> b = example.get_base()
>>> b.foo()
42
>>> b = example.get_other_base()
>>> b.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'OtherDerived' object has no attribute 'foo'
python 2022/1/1 18:31:52 有204人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶