使用相同的名称提升python getter / setter

时间:2017-05-28 20:22:46

标签: python c++ boost-python

我用boost-python包装C ++类,我想知道有没有比我现在做的更好的方法。

问题是这些类具有相同名称的getter / setter,并且似乎没有用boost-python包装它的无痛方法。

以下是问题的简化版本。鉴于此课程:

#include <boost/python.hpp>

using namespace boost::python;

class Foo {
public:
    double
    x() const
    {
        return _x;
    }

    void
    x(const double new_x)
    {
        _x = new_x;
    }

private:
    double _x;
};

我想做点什么:

BOOST_PYTHON_MODULE(foo)
{
    class_<Foo>("Foo", init<>())
        .add_property("x", &Foo::x, &Foo::x)
    ;
}

这不起作用,因为boost-python无法确定要使用的函数版本。

事实上,你甚至无法做到

.def("x", &Foo::x)

出于同样的原因。

我正在阅读boost.org上的教程,而section on overloading似乎非常有希望。不幸的是,它似乎并不是我想要的。

在重载部分,它提到了BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS宏,其工作方式如下:

如果Foo中有另一个成员函数接受了默认参数:

void z(int i=42)
{
    std::cout << i << "\n";
}

然后你可以使用宏:

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(z_member_overloads, z, 0, 1)

然后在BOOST_PYTHON_MODULE

.def("z", &Foo::z, z_member_overloads())

z_member_overloads允许你调用def一次,它会为0参数和1个参数公开python的方法。

我希望这对我的x()x(double val) getter / setter有用,但它不起作用。

做的:

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(x_member_overloads, x, 0, 1)
...
.def("x", &Foo::x, x_member_overloads())

无法编译:

error: no matching member function for call to 'def'

.def("x", &Foo::x, x_member_overloads())
~^~~

问题: 那么,是否有其他宏可以使这项工作成功?

为了完整起见,我正在处理这样的案例:

    .add_property(
        "x",
        make_function(
            [](Foo& foo) {
                return foo.x();
            },
            default_call_policies(),
            boost::mpl::vector<double, Foo&>()
        ),
        make_function(
            [](Foo& foo, const double val) {
                foo.x(val);
        },
        default_call_policies(),
        boost::mpl::vector<void, Foo&, double>()
        )
    )

1 个答案:

答案 0 :(得分:2)

您可以通过强制转换为适当的重载(未经测试)来执行此操作:

class_<Foo>("Foo", init<>())
        .add_property("x", 
                      static_cast< double(Foo::*)() const >(&Foo::x), // getter
                      static_cast< void(Foo::*)(const double) >(&Foo::x)) // setter
    ;