C++ to python with boost.python: Exposing virtual bool operator()(int )=0

Pedro pedroHereADotCrespoValeroATepflHereAdotch
Wed Mar 29 08:41:42 EST 2006


Hello pythonians! ;-D ,

I have a little problem when I expose (assisted by boost.python) classes 
with virtual functions, specially with operator().
In the C++ code below I test two different implementations of a member 
function of A that
takes as an argument the abstract class Base (see Option 1 / Option 2):
    - Both compile without problems
    - Only the second works in python (see python program below).

It seems like if the problem is in the way I expose operator()... but I 
do not understand it very well
Any clue about why this is happening?I would appreciate any comment on this.
Thank you very much in advance. :-D

Pedro.


//.......................................................
//................ C++ code......................
//.......................................................
#include <boost/python.hpp>
#define OPTION1
//#undef OPTION1

struct Base
{
    virtual ~Base() {}
    virtual int f() = 0;                            // Like in 
Boost.python tutorial
    virtual int g(int) = 0;                       // With 1 argument
    virtual bool operator()(int ii) =0;    //  __call__ - type function
};

class A{
private:
    int v_;
public:     A(int v): v_(v){}
   #ifdef OPTION1
    /* Option 1 */ int fun(Base& c) const { return 
c(v_)?(c.g(v_)+c.f()):33; }
#else
    /* Option 2 */ int fun(Base& c) const { return (c.g(v_)+c.f()); }
#endif
};

//:::::::::::::::::::::::::::BOOST::PYTHON in 
action:::::::::::::::::::::::::::
using namespace boost::python;

struct BaseWrap : Base, wrapper<Base>
{
    int f(){return call<int>(this->get_override("f").ptr());}
    int g(int ii){return call<int>(this->get_override("g").ptr(),ii);}
    bool operator()(int ii){ return 
call<bool>(this->get_override("operator()").ptr(),ii);}
};

BOOST_PYTHON_MODULE(test2py)
{
    class_<A>("A",init<int>())
        .def("fun",&A::fun);

    class_<BaseWrap, boost::noncopyable>("Base")
        .def("f", pure_virtual(&Base::f))
        .def("g", pure_virtual(&Base::g))
        .def("__call__", pure_virtual(&Base::operator()))         ;
};


//.......................................................
//................ Python code...................
//.......................................................

from test2py import *


## Extension of C++ class in python
class Derived(Base):
    def f(self):
        return 44
    def g(self,n):
        return n
    def __call__(self, v):
        return (v<23)


d=Derived()
print d.f()
print d.g(3)
print "is 20<23 and 24<23", d(20), d(24)


a=A(20)
print a.fun(d)

b=A(24)
print b.fun(d)


//......................................................................
//................ Executing Python code..................
//.....................................................................


With Option 1 IS NOT WORKING!!
    ...
int fun(Base& c) const { return c(v_)?(c.g(v_)+c.f()):33; }
    ...

 >>>
44
3
is 20<23 and 24<23 True False
Traceback (most recent call last):
  File "d:\My_Documents\src\pysource\test.py", line 29, in ?
    print a.fun(d)
TypeError: 'NoneType' object is not callable


With Option 2 IS WORKING!!
    ...
int fun(Base& c) const { return (c.g(v_)+c.f()); }
    ...

 >>>
44
3
is 20<23 and 24<23 True False
64
68
 >>>





More information about the Python-list mailing list