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: $ 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