Re: [C++-sig] Inheritance problem
Hi,
> currently i am facing a problem regarding inheritance with boost::python
>
> Here is a simple code snippet:
>
>
> class Base
> {
> public:
> virtual void print() { std::cout << "hello" << std::endl; }
>
> };
>
> [...]
>
> And in python i want to have the following reslut:
>
> >>import my_module
> >> derived = my_module.Derived()
> >> derived.printIt()
>
> Actually this should print "hello" but instead throws an error saying:
>
> derived.printIt()
> Boost.Python.ArgumentError: Python argument types in
> Base.printIt(Derived)
> did not match C++ signature:
> printIt(_Base {lvalue})
Maybe I'm oversimplifying but if all you need is exposing some derived
class then
I don't see why you'd need all the BaseWrapper, self-pointer etc. stuff.
S.th. as simple as that should work:
// file cppcode.hpp
#include
class Base
{
public:
virtual void print() { std::cout << "hello Base" << std::endl; }
};
class Derived : public Base
{
public:
virtual void print() { std::cout << "hello Derived" << std::endl; }
};
// only to show callback-into-python-overrides necessities
void callback(Base& base) {
base.print();
}
// file wrap.cpp
#include
#include "cppcode.hpp"
namespace bp = boost::python;
BOOST_PYTHON_MODULE(cppcode)
{
bp::class_("Base")
.def("printIt", &Base::print)
;
bp::class_ >("Derived");
bp::def("callback", &callback);
};
When run:
# file test.py
import cppcode
derived = cppcode.Derived()
derived.printIt()
cppcode.callback(derived)
class PythonDerived(cppcode.Base):
def printIt(self):
print "hello PythonDerived"
pyderived = PythonDerived()
pyderived.printIt()
cppcode.callback(pyderived)
$ python2.7 -i ./test.py
hello Derived
hello Derived
hello PythonDerived
hello Base
>>>
Note that you'd need a Base wrapper class to actually make callbacks to
Python method-overrides work,
just as documented in
http://www.boost.org/doc/libs/1_47_0/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions
Holger
Landesbank Baden-Wuerttemberg
Anstalt des oeffentlichen Rechts
Hauptsitze: Stuttgart, Karlsruhe, Mannheim, Mainz
HRA 12704
Amtsgericht Stuttgart
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] Inheritance problem
On 10/14/11 10:29, Holger Joukl wrote:
Hi,
currently i am facing a problem regarding inheritance with boost::python
Here is a simple code snippet:
class Base
{
public:
virtual void print() { std::cout<< "hello"<< std::endl; }
};
[...]
And in python i want to have the following reslut:
>>import my_module
>> derived = my_module.Derived()
>> derived.printIt()
Actually this should print "hello" but instead throws an error saying:
derived.printIt()
Boost.Python.ArgumentError: Python argument types in
Base.printIt(Derived)
did not match C++ signature:
printIt(_Base {lvalue})
Maybe I'm oversimplifying but if all you need is exposing some derived
class then
I don't see why you'd need all the BaseWrapper, self-pointer etc. stuff.
S.th. as simple as that should work:
// file cppcode.hpp
#include
class Base
{
public:
virtual void print() { std::cout<< "hello Base"<< std::endl; }
};
class Derived : public Base
{
public:
virtual void print() { std::cout<< "hello Derived"<< std::endl; }
};
// only to show callback-into-python-overrides necessities
void callback(Base& base) {
base.print();
}
// file wrap.cpp
#include
#include "cppcode.hpp"
namespace bp = boost::python;
BOOST_PYTHON_MODULE(cppcode)
{
bp::class_("Base")
.def("printIt",&Base::print)
;
bp::class_ >("Derived");
bp::def("callback",&callback);
};
When run:
# file test.py
import cppcode
derived = cppcode.Derived()
derived.printIt()
cppcode.callback(derived)
class PythonDerived(cppcode.Base):
def printIt(self):
print "hello PythonDerived"
pyderived = PythonDerived()
pyderived.printIt()
cppcode.callback(pyderived)
$ python2.7 -i ./test.py
hello Derived
hello Derived
hello PythonDerived
hello Base
Note that you'd need a Base wrapper class to actually make callbacks to
Python method-overrides work,
just as documented in
http://www.boost.org/doc/libs/1_47_0/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions
Holger
Landesbank Baden-Wuerttemberg
Anstalt des oeffentlichen Rechts
Hauptsitze: Stuttgart, Karlsruhe, Mannheim, Mainz
HRA 12704
Amtsgericht Stuttgart
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Hi Holger,
thanks for your response.
Ok lets say my BaseClass has a member function called init( vector4 ):
class Base
{
public:
void init( vector4 &vec ) { //doWhatEver }
//a lot of other functions
};
Unfortunetaly i can not expose this init function directly to python so
i am writing a BaseWrapper
class BaseWrapper : public Base, public bp::wrapper
{
public:
void _init( int first, int second, int third, int fourth) { init(
makeVec(first, second, third, fourth) ); }
// a lot of other wrapper functions
};
And i have a derived class:
class Derived : Base
{
public:
//some more functions
};
So when i am exposing Base and Derived like:
BOOST_PYTHON_MODULE( my_module )
{
class_( "Base", init<>() )
.def("init", &BaseWrapper::_init)
;
class_ >( "Derived", init<>() );
}
I want to have all functions for objects of Derived that are available
in Base.
The thing is, that e.g. ipython recognizes the functions.
So in ipython, when i have an object of type Derived with tab completion
i see the functions from Base.
But when i try to call them i always get this "signature" error.
So i do not know how to use those callback approach you suggested.
Especially if you are using function overloading. And additionally, this
would mean, that i have to write such a callback function for each
function in my base class as a global function.
I think there is a much simpler way.
One thing i have to mention is, that it is perfectly working if i omit
the BaseWrapper class. So if the functions of Base can be exposed
without using a wrapper class:
class Base
{
public:
void init( int first, int second, int third, int fourth ) {
//doWhatEver }
//a lot of other functions
};
class Derived : public Base
{
};
BOOST_PYTHON_MODULE( my_module )
{
class_( "Base", init<>() )
.def("init", &Base::init)
;
class_ >( "Derived", init<>() );
}
In python:
>>derived = my_module.Derived()
>>derived.init(3,1,2,2)
...works. But unfortunately not with the BaseWrapper Class :-(
Sorry for the long post...
Best regards!
--
Erik Türke
Department of Neurophysics
Max-Planck-Institute for Human Cognitive and Brain Sciences
Stephanstrasse 1A
04103 Leipzig
Germany
Tel: +49 341 99 40-2440
Email: [email protected]
www.cbs.mpg.de
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] Inheritance problem
Hi,
> Ok lets say my BaseClass has a member function called init( vector4 ):
>
> class Base
> {
> public:
> void init( vector4 &vec ) { //doWhatEver }
> //a lot of other functions
> };
>
> Unfortunetaly i can not expose this init function directly to python so
> i am writing a BaseWrapper
Why's that? Can't you expose vector4 to Python?
> So when i am exposing Base and Derived like:
>
>
> BOOST_PYTHON_MODULE( my_module )
> {
>
> class_( "Base", init<>() )
> .def("init", &BaseWrapper::_init)
> ;
> class_ >( "Derived", init<>() );
> }
>
> I want to have all functions for objects of Derived that are available
> in Base.
> The thing is, that e.g. ipython recognizes the functions.
> So in ipython, when i have an object of type Derived with tab completion
> i see the functions from Base.
> But when i try to call them i always get this "signature" error.
I think the problem is that the Derived class doesn't actually have any
inheritance
relationship with BaseWrapper, i.e.
Base
/ \
/ \
/ \
BaseWrapper Derived
So in an example like this
// file cppcode.hpp
#include
class Base
{
protected:
int m_area;
public:
Base() : m_area(0) {}
void init(int area) {
m_area = area;
}
virtual void print() { std::cout << "hello Base " << m_area <<
std::endl; }
};
class Derived : public Base
{
public:
virtual void print() { std::cout << "hello Derived " << m_area <<
std::endl; }
};
// only to show callback-into-python-overrides necessities
void callback(Base& base) {
base.print();
}
// file wrap.cpp
#include
#include "cppcode.hpp"
namespace bp = boost::python;
class BaseWrapper : public Base, public bp::wrapper
{
public:
void _init(int x, int y) {
init(x * y);
}
};
BOOST_PYTHON_MODULE(cppcode)
{
bp::class_("Base")
.def("init", &BaseWrapper::_init)
.def("printIt", &Base::print)
;
bp::class_ >("Derived");
bp::def("callback", &callback);
};
#!/apps/local/gcc/4.5.1/bin/python2.7
# file test.py
import cppcode
print "---> base"
base = cppcode.Base()
base.printIt()
base.init(3, 4)
base.printIt()
print "---> derived"
derived = cppcode.Derived()
derived.printIt()
derived.init(3, 4)
derived.printIt()
cppcode.callback(derived)
class PythonDerived(cppcode.Base):
def printIt(self):
print "hello PythonDerived"
print "---> python derived"
pyderived = PythonDerived()
pyderived.printIt()
cppcode.callback(pyderived)
I run into this error when trying to call .init() on the Derived object:
$ python2.7 ./test.py
---> base
hello Base 0
hello Base 12
---> derived
hello Derived 0
Traceback (most recent call last):
File "./test.py", line 23, in
derived.init(3, 4)
Boost.Python.ArgumentError: Python argument types in
Base.init(Derived, int, int)
did not match C++ signature:
init(BaseWrapper {lvalue}, int, int)
Which makes sense since Derived does not inherit from BaseWrapper.
> So i do not know how to use those callback approach you suggested.
> Especially if you are using function overloading. And additionally, this
> would mean, that i have to write such a callback function for each
> function in my base class as a global function.
Never mind the callback, I might have just confused you. The callback is
only for showing
that you'd need a Wrapper class if you want to inherit in Python and be
able to call back
from C++ into Python and actually call methods overridden in Python.
> One thing i have to mention is, that it is perfectly working if i omit
> the BaseWrapper class. So if the functions of Base can be exposed
> without using a wrapper class:
> [...]
> ...works. But unfortunately not with the BaseWrapper Class :-(
Because now you don't have the problem that Derived has no inheritance
relationship with BaseWrapper.
Maybe you can just use a free function:
// file wrap.cpp
#include
#include "cppcode.hpp"
namespace bp = boost::python;
void _init(Base& base, int x, int y) {
base.init(x * y);
}
BOOST_PYTHON_MODULE(cppcode)
{
bp::class_("Base")
.def("init", &_init)
.def("printIt", &Base::print)
;
bp::class_ >("Derived");
bp::def("callback", &callback);
};
# file test.py
import os
import sys
import cppcode
print "---> base"
base = cppcode.Base()
base.printIt()
base.init(3, 4)
base.printIt()
print "---> derived"
derived = cppcode.Derived()
derived.printIt()
derived.init(3, 4)
derived.printIt()
cppcode.callback(derived)
class PythonDerived(cppcode.Base):
def printIt(self):
print "hello PythonDerived"
print "---> python derived"
pyderived = PythonDerived()
pyderived.printIt()
# to make this invoke PythonDerived.printIt() you need a wrapper class
cppcode.callback(pyderived)
===>
$ python2.7 ./test.py
---> base
hello Base 0
hello Base 12
---> derived
hello Derived 0
hello Derived 12
hello Derived 12
---> python derived
hello PythonDerived
hello Base 0
>>>
Holger
Lan
