当前位置: 首页 > 面试题库 >

在Boost Python中公开C ++接口

李烨烁
2023-03-14
问题内容

示例代码说明:

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教程提供了有关如何公开纯虚函数的示例。简而言之,当使用修饰装饰方法时 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_文档指出:

模板参数:

  • T:正在包装的课程
  • HeldType:指定包装T实例的Python对象中实际嵌入的类型[…]。默认为T

因此,该操作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'


 类似资料:
  • 本文向大家介绍C#开发微信公众号接口开发,包括了C#开发微信公众号接口开发的使用技巧和注意事项,需要的朋友参考一下 具体实现方式不多说了,请看下文 一、前言 当下微信公众号几乎已经是每个公司必备的,但是大部分微信公众账号用户体验都欠佳,特别是涉及到用户绑定等,需要用户进行复杂的操作才可以和网站绑定,或者很多公司直接不绑定,而是每次都让用户填写账号密码。作为微信接口开发人员我们知道网页授权可以用作微

  • 问题内容: 我目前正在研究一个项目,因为我必须用Python包装C ++类才能编写程序脚本。因此,我的具体经验还涉及将Python解释器嵌入到我们的程序中。 我尝试的替代方法是: Boost.Python 我喜欢Boost.Python生成的更清洁的API,但事实是它需要用户安装其他依赖项,这一事实使我们切换到SWIG。 斯威格 SWIG对我们而言的主要优势在于,它不需要最终用户安装它即可使用最终

  • 问题内容: 我刚刚尝试发现它现在不包含本机方法,而是将它们委托给some ,例如: 反过来,最新的实际上看起来像旧的,但是现在这些方法都带有一些注释: 那么,使用启动JDK9是否“安全” ?现在是公共官方API吗? 问题答案: 这是一个很好的解释: https://adtmag.com/blogs/watersworks/2015/08/java-9-hack.aspx 在Java 9中如何处理s

  • 本文向大家介绍C#微信公众号与订阅号接口开发示例代码,包括了C#微信公众号与订阅号接口开发示例代码的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#微信公众号与订阅号接口开发示例代码。分享给大家供大家参考,具体如下: 更多关于C#相关内容感兴趣的读者可查看本站专题:《C#常见控件用法教程》、《WinForm控件用法总结》、《C#数据结构与算法教程》、《C#面向对象程序设计入门教程》及《C

  • 考虑一个声明了以下功能 我想在Java中公开,但不

  • 我正在使用AzureAd Powershell模块进行用户管理。但是,它并不具备我所需要的所有功能,特别是,我不能为对象分配应用程序扩展值(尽管我可以通过创建删除和删除应用程序扩展本身)。 通过观察使用Fiddler的API调用,我知道graph调用使用了承载令牌,并且我直接从Postman手动调用了graph API,所以如果可以的话,我知道如何使用承载令牌。我怎么拿到?

  • 问题内容: 通过阅读AWS文档,似乎将Docker用作Elastic Beanstalk(EB)(与Tomcat等相对)的平台时,只能公开一个端口。我试图了解为什么亚马逊创建了此限制- 看来您现在甚至无法同时提供HTTP和HTTPS。 我想使用Docker作为容器,因为它允许我在同一容器中运行多个互连的服务器进程,其中一些需要多个端口(例如RTSP)。对于这种应用程序,是否有任何变通办法,例如RT

  • 是否可以在restendpoint中公开所有的Spring度量? 我使用的是spring Boot2.2.2并添加了这个依赖项 application.yml