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
> [email protected]
> https://mail.python.org/mailman/listinfo/cplusplus-sig
_______________________________________________
Cplusplus-sig mailing list
[email protected]
https://mail.python.org/mailman/listinfo/cplusplus-sig