P
Pedro
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:YTHON in
action:::::::::::::::::::::::::::
using namespace boost:ython;
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:perator())) ;
};
//.......................................................
//................ 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
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:YTHON in
action:::::::::::::::::::::::::::
using namespace boost:ython;
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:perator())) ;
};
//.......................................................
//................ 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