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

Reply via email to