【问题标题】:How to wrap with boost-python a virtual class with a method returning a reference如何用 boost-python 包装一个带有返回引用的方法的虚拟类
【发布时间】:2012-01-27 09:25:07
【问题描述】:

我有两个虚拟类我想用 boost python 包装,我希望能够编写扩展它们的 Python 类。问题是,其中一个类有一个返回另一个类的引用的方法,我不知道该怎么做。

这是要包装的类代码的简化版本。

class Foo
{
    public:
    virtual ~Foo() {}
    virtual int a() = 0;
};

class Bar
{
    public:
    virtual ~Bar() {}
    virtual Foo const& b() = 0;
};

所以我开始用这种方式包装。

class FooWrap : public Foo, public wrapper<Foo>
{
    public:
    int a()
    {
        return this->get_override("a")();
    }
};

class BarWrap : public Bar, public wrapper<Bar>
{
    public:
    Foo const& b()
    {
        return this->get_override("b")();
    }
};

BOOST_PYTHON_MODULE(foobar)
{
    class_<FooWrap, boost::noncopyable>("Foo")
        .def("a", pure_virtual(&Foo::a))
        ;
    class_<BarWrap, boost::noncopyable>("Bar")
        .def("b", pure_virtual(&Bar::b))
        ;
}

我收到一个关于“无法实例化抽象类 [...] 纯虚函数未定义" "参见 'foo::a' 的声明"

【问题讨论】:

  • 如果虚函数和封装类的继承是公开的呢?
  • 不,将所有内容设为公开并不能解决我的问题。
  • @MatthieuW 是否可以将函数的返回类型修改为智能指针?
  • @Paul-Manta 不,我的目标是测试一个 c++ 库,我无法更改它的接口。

标签: c++ python boost-python


【解决方案1】:

在为Bar::b 函数添加调用策略后,我已经能够编译和运行您的代码:

BOOST_PYTHON_MODULE(foobar)
{
    class_<FooWrap, boost::noncopyable>("Foo")
        .def("a", pure_virtual(&Foo::a));

    class_<BarWrap, boost::noncopyable>("Bar")
        .def("b", pure_virtual(&Bar::b),
             return_internal_reference<>());
}

基本上,这只是意味着从Bar::b 返回的引用的生命周期应该取决于Bar 实例的生命周期。您可以在boost docs 阅读有关通话政策的信息。

您使用的是什么编译器和 boost 版本? boost 1.46.0 和 gcc 4.6.1 出现以下描述性错误:

error: no match for call to ‘(const boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<const Foo&>) (const Foo&)’

【讨论】:

  • 我使用 boost 1.47.0 和 VC 7.1
  • 在 MSVC 6 和 7 的 boost 文档中有 cmets:你应该试试 return call&lt;int&gt;(this-&gt;get_override("a").ptr());
  • 就是这样。 MSVC 7 的东西。到现在为止,我使用的是通常的语法并且它工作得很好,所以我认为不再需要 MSVC 7 的特殊语法。实际上在某些情况下是这样。
  • 更准确的说是方法b需要。 return boost::python::call(this->get_override("b").ptr());
【解决方案2】:

以下代码为我编译。在您的 python Bar 子类中,您应该能够从 b 方法返回一个 Foo 实例。

#include <boost/python.hpp>

class Foo
{
public:
    virtual ~Foo() {}
    virtual int a() = 0;
};

class Bar
{
public:
    virtual ~Bar() {}
    virtual Foo const& b() = 0;
};


class FooWrap : public Foo, public boost::python::wrapper<Foo>
{
    public:
    int a()
    {
        return this->get_override("a")();
    }
};

class BarWrap : public Bar, public boost::python::wrapper<Bar>
{
    public:
    Foo const& b()
    {
        return this->get_override("b")();
    }
};

BOOST_PYTHON_MODULE(foobar)
{
    boost::python::class_<FooWrap, boost::noncopyable>("Foo")
        .def("a", boost::python::pure_virtual(&Foo::a)) ;

    boost::python::class_<BarWrap, boost::noncopyable>("Bar")
        .def("b", boost::python::pure_virtual(&Bar::b), boost::python::return_internal_reference<>());
}

【讨论】:

    猜你喜欢
    • 2011-10-03
    • 1970-01-01
    • 2011-01-17
    • 2020-06-20
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    相关资源
    最近更新 更多