如何使用boost-python包装返回引用的虚类方法

3 投票
2 回答
3002 浏览
提问于 2025-04-17 11:12

我有两个虚拟类想要用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'的声明”。

2 个回答

3

下面的代码在我这边可以正常编译。在你的 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<>());
}
4

我在你的代码中添加了对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文档中了解更多关于调用策略的信息。

你使用的编译器和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&)’

撰写回答