Hi, On Tue, 2015-01-13 at 12:13 +0100, Holger Joukl wrote: > Hi, > > > For ElementWrap::get_float, try: > > float get_float() { return this->get_override("get_float")(); } > > > > Binding to Python of that function should then be: > > .def("get_float", pure_virtual(&Element::get_float)) > > > > See also: > > http://www.boost.org/doc/libs/1_57_0/libs/python/doc/tutorial/doc/ > > html/python/exposing.html#python.class_virtual_functions > > > > With regards, > > > > Paul > > Doesn't solve this problem:
I confirm what Holger said. Paul's reply doesn't solve the problem. In fact, if I change the ElementWrap::get_float to: virtual float get_float() { return this->get_override("get_float")(); } I get in python: Traceback (most recent call last): File "m2.py", line 18, in <module> print (element.get_float()) TypeError: 'NoneType' object is not callable Which is very odd. It seems that boost get_override is not able to find the overloaded python SubElement.get_float() method. For reference I am using a Debian 7 machine 64bits. Python 2.7.3 GCC 4.7.2 boost-python 1.49.0 Thanks for all your help. Kind regards, Tiago > > $ cat m1_py.cpp > // m1_py.cpp > #include "boost/python.hpp" > #include <memory> > #include "m1.hpp" > > > > class ElementWrap : public Element, public boost::python::wrapper<Element> > { > public: > // Element::get_float is pure virtual so no need for default > implementation > // if no python override found > virtual float get_float() { > boost::python::override py_override = this->get_override > ("get_float"); > if (!py_override) { > // want a nice error message if no Python override of the > // pure virtual method has been found > boost::python::detail::pure_virtual_called(); > } > return py_override(); > } > }; > > > > void set_element(Owner& owner, std::auto_ptr<ElementWrap> e) > { > owner.set_element(e.get()); > e.release(); > } > > > BOOST_PYTHON_MODULE(m1) { > > boost::python::class_<ElementWrap, std::auto_ptr<ElementWrap>, > boost::noncopyable>( > "Element", > boost::python::init<>()) > .def("get_int", &Element::get_int) > .def("get_float", boost::python::pure_virtual(&Element::get_float)) > ; > > > boost::python::class_<Owner>("Owner", boost::python::init<>()) > .def("set_element", &set_element) > .def("get_element", &Owner::get_element, > boost::python::return_internal_reference<>()) > ; > } > 0 $ cat m2.py > # m2.py > > import m1 > > class SubElement(m1.Element): > > def get_float(self): > return 4.5678 + self.get_int() > > element = SubElement() > print "element:", element > owner = m1.Owner() > print "element.get_int():", > print element.get_int() > print "owner.set_element(element)..." > owner.set_element(element) > print "element:", element > try: > print "element.get_int():", > print element.get_int() > except Exception as e: > print "*** Exception caught:" > print e > print "element = owner.get_element(element)..." > element = owner.get_element() > print "element:", element > > # ops! > print (element.get_float()) > > 0 $ PYTHONPATH=./bin/gcc-4.6.1/debug/ python2.7 m2.py > element: <__main__.SubElement object at 0x7fef49783100> > element.get_int(): -1 > owner.set_element(element)... > element: <__main__.SubElement object at 0x7fef49783100> > element.get_int(): *** Exception caught: > Python argument types in > Element.get_int(SubElement) > did not match C++ signature: > get_int(Element {lvalue}) > element = owner.get_element(element)... > element: <__main__.SubElement object at 0x7fef49783100> > Traceback (most recent call last): > File "m2.py", line 29, in <module> > print (element.get_float()) > File "m2.py", line 8, in get_float > return 4.5678 + self.get_int() > Boost.Python.ArgumentError: Python argument types in > Element.get_int(SubElement) > did not match C++ signature: > get_int(Element {lvalue}) > > > We don't even get to the code to invoke a Python override here. > > Note how after owner.set_element() the SubElement instance becomes > "inoperational". > > I don't quite understand the boost.python inner workings but the call to > void set_element(Owner& owner, std::auto_ptr<ElementWrap> e) > transfers ownership to the local auto_ptr e, so the auto_ptr held from > the Python side gets modified (released ownership, now pointing to null). > > Much the same result as with the original implementation (although I seem > to get the same object id for the get_element() return value here but that > might be coincidence). > > Holger > > Landesbank Baden-Wuerttemberg > Anstalt des oeffentlichen Rechts > Hauptsitze: Stuttgart, Karlsruhe, Mannheim, Mainz > HRA 12704 > Amtsgericht Stuttgart > > _______________________________________________ > Cplusplus-sig mailing list > Cplusplus-sig@python.org > https://mail.python.org/mailman/listinfo/cplusplus-sig _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org https://mail.python.org/mailman/listinfo/cplusplus-sig