在boost python中暴露C接口

前端之家收集整理的这篇文章主要介绍了在boost python中暴露C接口前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
示例代码说明:
struct Base
{
  virtual int foo() = 0;
};

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

Base* get_base()
{
  return new Derived;
}

BOOST_PYTHON_MODULE(libTestMod)
{
  py::class_<Base>("Base",py::no_init)
    .def("foo",py::pure_virtual(&Base::foo));

  py::def("get_base",get_base,py::return_internal_reference<>()); //ignore mem leak
}

> Base :: foo不会在python中被覆盖
> Base:foo将在c中实现,但不应该暴露在python中

试过上面的代码,但无法编译.

更新:
编译错误

/path/to/boostlib/boost/1.53.0-0/common/include/boost/python/object/value_holder.hpp:66:11: error: cannot declare field 'boost_1_53_0::python::objects::value_holder<Base>::m_held' to be of abstract type 'Base'
Main.C:59:8: note:   because the following virtual functions are pure within 'Base':
Main.C:61:15: note:         virtual int Base::foo()

解决方法

抽象C类不能以这种方式暴露给Boost.Python. Boost.Python tutorial提供了如何公开纯虚拟函数的示例.简而言之,当使用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_文档规定:

Template Parameter:

  • T: The class being wrapped
  • HeldType: Specifies the type that is actually embedded in a Python object wrapping a T instance […]. Defaults to T.

因此,boost :: python :: class_< Base>将失败,因为T = Base和HeldType = Base,Boost.Python将尝试将HeldType的对象实例化为表示Base实例的Python对象.这个实例化将失败,因为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中暴露一个抽象类是可能的,它没有默认的初始化器(boost :: python :: no_init)和不可复制(boost :: noncopyable).缺少一个初始化器可以防止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",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>",in <module>
AttributeError: 'OtherDerived' object has no attribute 'foo'

猜你在找的C&C++相关文章