Я оборачиваю классы С++ с помощью boost-python, и мне интересно, есть ли лучший способ сделать это, чем то, что я делаю сейчас.
Проблема в том, что у классов есть геттеры/сеттеры с одинаковыми именами, и кажется, что нет безболезненного способа обернуть это с помощью 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 и раздел о перегрузке казался многообещающим. К сожалению, похоже, это не то, что я ищу.
В разделе перегрузки упоминается макрос 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
один раз, и он предоставит методы python как для 0 аргументов, так и для 1 аргумента.
Я надеялся, что это сработает для моих геттеров/сеттеров x()
и x(double val)
, но это не сработало.
делает:
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>()
)
)