man*_*ake 11 python boost boost-python
我正在使用Boost.Python从C++类创建Python模块.我遇到了引用的问题.
Condider以下情况我有一个类Foo,带有重载的get方法,可以通过值或引用返回.
一旦我输入了签名,指定应该使用值返回很容易.但我认为应该可以通过使用a返回引用 return_value_policy.但是,使用看似合适的东西(doc); return_value_policy<reference_existing_object>似乎没有用.
我误解了它的作用吗?
struct Foo {
Foo(float x) { _x = x; }
float& get() { return _x; }
float get() const { return _x; }
private:
float _x;
};
// Wrapper code
BOOST_PYTHON_MODULE(my_module)
{
using namespace boost::python;
typedef float (Foo::*get_by_value)() const;
typedef float& (Foo::*get_by_ref)();
class_<Foo>("Foo", init<float>())
.def("get", get_by_value(&Foo::get))
.def("get_ref", get_by_ref(&Foo::get),
return_value_policy<reference_existing_object>())//Doesn't work
;
}
Run Code Online (Sandbox Code Playgroud)
注意:我知道在没有生命周期管理的情况下引用现有对象可能会很危险.
更新:
看起来它适用于对象但不适用于基本数据类型.
拿这个修改过的例子:
struct Foo {
Foo(float x) { _x = x; }
float& get() { return _x; }
float get() const { return _x; }
void set( float f ){ _x = f;}
Foo& self(){return *this;}
private:
float _x;
};
// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
typedef float (Foo::*get_by_value)() const;
class_<Foo>("Foo", init<float>())
.def("get", get_by_value(&Foo::get))
.def("get_self", &Foo::self,
return_value_policy<reference_existing_object>())
.def("set", &Foo::set);
;
}
Run Code Online (Sandbox Code Playgroud)
在测试中给出了预期的结果:
>>> foo1 = Foo(123)
>>> foo1.get()
123.0
>>> foo2 = foo1.get_self()
>>> foo2.set(1)
>>> foo1.get()
1.0
>>> id(foo1) == id(foo2)
False
Run Code Online (Sandbox Code Playgroud)
在Python中,有不可变类型的概念.不可变类型的值不能更改.内置不可变类型的示例是int,float和str.
话虽如此,你不能做你想要的boost::python,因为Python本身不允许你改变函数返回的float的值.
您的第二个示例显示了一个解决方案,另一个示例是创建精简包装并公开:
void Foo_set_x(Foo& self, float value) {
self.get() = value;
}
class_<Foo>("Foo", init<float>())
...
.def("set", &Foo_set_x);
;
Run Code Online (Sandbox Code Playgroud)
哪个是比更改原始C++类更好的解决方案.