Używam Boost.Python do tworzenia modułów Python z klas C++. I natknąłem się na problem z referencjami.Boost.Python - jak wrócić przez referencję?
Weź pod uwagę następujący przypadek, w którym mam klasę Foo z przeciążonymi metodami uzyskiwania, które mogą zwracać wartość lub odwoływać się.
Określenie, że zwrot po wartości powinien być użyty, było łatwe po tym, jak wpisałem podpis. Ale myślę, że powinno być możliwe zwrócenie referencji również za pomocą return_value_policy
. Jednak użycie tego, co wydawało się odpowiednie (doc); return_value_policy<reference_existing_object>
nie działa.
Czy źle zrozumiałem, co robi?
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
;
}
Uwaga: Wiem, że to może być niebezpieczne odwołać istniejącego obiektu bez zarządzających czas życia.
Aktualizacja:
Wygląda na to, że pracuje dla obiektów, ale nie podstawowe typy danych.
Weź tę poprawioną przykład:
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);
;
}
które w teście dało oczekiwany rezultat:
>>> foo1 = Foo(123)
>>> foo1.get()
123.0
>>> foo2 = foo1.get_self()
>>> foo2.set(1)
>>> foo1.get()
1.0
>>> id(foo1) == id(foo2)
False
Tak, wiem, że wszystko to odniesienia w Pythonie. Kiedy tworzę metodę Pythona z Boost.Python, który zwraca "według wartości", zwraca kopię tego typu. Chcę tylko * nie * skopiować, ale zamiast tego utworzyć odniesienie do tej samej instancji. – mandrake