[C++-sig] [Boost Python] Cannot call base method from within python extended class method
Tiago Coutinho
coutinho at esrf.fr
Thu Jan 8 18:42:14 CET 2015
Hello,
My problem is the following:
I am trying to bind a third party C++ library to python using
boost-python.
This library has a class Element and a class Owner (the later takes
ownership
of an Element object).
To make things interesting, Element defines a pure virtual method
"get_float".
The Element should be sub-classed in python. Here is a simplified
version of the
library:
// m1.hpp
---------------------------------------------------------------------
// m1.hpp
class Element {
public:
int get_int() { return -1; }
virtual float get_float() = 0;
};
class Owner {
Element *m_element;
public:
Owner(): m_element(NULL) {}
~Owner() { delete m_element; }
void set_element(Element* e) {
delete m_element;
m_element = e;
};
Element* get_element() { return m_element; }
};
and here is how I am binding to python:
// m1_py.cpp
----------------------------------------------------------------
class ElementWrap : public Element,
public wrapper<Element>
{
public:
PyObject* self;
ElementWrap(PyObject* self_): Element(), self(self_)
{ Py_INCREF(self); }
~ElementWrap() { Py_DECREF(self); }
virtual float get_float() { return call_method<float>(self,
"get_float"); }
};
void set_element(Owner& owner, auto_ptr<Element> e) {
owner.set_element(e.get());
e.release();
}
BOOST_PYTHON_MODULE(m1) {
class_<Element, auto_ptr<ElementWrap>,
boost::noncopyable>("Element", init<>())
.def("get_int", &Element::get_int)
.def("get_float", &Element::get_float)
;
register_ptr_to_python<auto_ptr<Element> >();
implicitly_convertible<auto_ptr<ElementWrap>, auto_ptr<Element> >();
class_<Owner>("Owner", init<>())
.def("set_element", &set_element)
.def("get_element", &Owner::get_element, return_internal_reference<>())
;
}
... but when I use it like this:
# m2.py
-----------------------------------------------------------------------
import m1
class SubElement(m1.Element):
def get_float(self):
return 4.5678 + self.get_int()
element = SubElement()
owner = m1.Owner()
owner.set_element(element)
element = owner.get_element()
# ops!
print (element.get_float())
I get an exception in the last line:
Traceback (most recent call last):
File "m2.py", line 16, in <module>
print (element.get_float())
File "m2.py", line 8, in get_float
return 1.0 + self.get_int()
Boost.Python.ArgumentError: Python argument types in
Element.get_int(SubElement)
did not match C++ signature:
get_int(Element {lvalue})
It seems that when I passed ownership to python I lost the ability to
call
a method from the base class.
Can anyone help me?
Thanks in advance
Cheers
Tiago
More information about the Cplusplus-sig
mailing list