[C++-sig] Inheritance problem

Erik Türke tuerke at cbs.mpg.de
Fri Oct 14 11:22:48 CEST 2011


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<iostream>
>
> 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<boost/python.hpp>
> #include "cppcode.hpp"
>
> namespace bp = boost::python;
>
>
>
> BOOST_PYTHON_MODULE(cppcode)
> {
>      bp::class_<Base>("Base")
>          .def("printIt",&Base::print)
>       ;
>      bp::class_<Derived, bp::bases<Base>  >("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
> Cplusplus-sig at python.org
> 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<Base>
{
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, BaseWrapper>( "Base", init<>() )
     .def("init", &BaseWrapper::_init)
     ;
     class_<Derived, bases<Base> >( "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>( "Base", init<>() )
     .def("init", &Base::init)
     ;
     class_<Derived, bases<Base> >( "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: tuerke at cbs.mpg.de
www.cbs.mpg.de



More information about the Cplusplus-sig mailing list