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

Reply via email to