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