On 10/14/11 16:48, Holger Joukl wrote:
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, 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.
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<iostream>

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<boost/python.hpp>
#include "cppcode.hpp"

namespace bp = boost::python;


class BaseWrapper : public Base, public bp::wrapper<Base>
{
  public:
     void _init(int x, int y) {
         init(x * y);
     }
};


BOOST_PYTHON_MODULE(cppcode)
{
     bp::class_<BaseWrapper, boost::noncopyable>("Base")
         .def("init",&BaseWrapper::_init)
         .def("printIt",&Base::print)
      ;
     bp::class_<Derived, bp::bases<Base>  >("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<module>
     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<boost/python.hpp>
#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>("Base")
         .def("init",&_init)
         .def("printIt",&Base::print)
      ;
     bp::class_<Derived, bp::bases<Base>  >("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

Landesbank Baden-Wuerttemberg
Anstalt des oeffentlichen Rechts
Hauptsitze: Stuttgart, Karlsruhe, Mannheim, Mainz
HRA 12704
Amtsgericht Stuttgart

_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig
Hi Holger,

well, ok, i understand now what the problem is. Many thanks for your help!

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: tue...@cbs.mpg.de
www.cbs.mpg.de

_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to