[C++-sig] How to wrap many virtual function

Dennis Brakhane Dennis.Brakhane at urz.uni-heidelberg.de
Fri Sep 16 01:23:10 CEST 2005


Hello list!

I want to wrap an interface that uses many virtual functions, some of 
them pure virtual, with many derived classes. Consider the following 
example:


struct Foo
{
     Foo(int a, int b=42);

     virtual ~Foo();

     virtual void v() = 0;
     virtual void v2();

     void showab();
     int a,b;

};

void Foo::v2()
{cout<<"foo v2"<<endl;}

struct Bar : public Foo
{
     Bar(int a,int b=42) : Foo(a,b) {}
     virtual void v();

};


void Bar::v()
{
     cout << "v" << endl;
}

void call_v(Foo& foo)
{
     foo.v();
}

void call_v2(Foo& foo)
{
     foo.v2();
}

struct FooWrap : public Foo, wrapper<Foo>
{
     void v() {this->get_override("v")();}
     void v2() {
	if (override f = this->get_override("v2"))
	    f();
	else
	    Foo::v2();
     }
     void default_v2()
	{
	    this->Foo::v2();
	}

     FooWrap(int a, int b=42)
	: Foo(a,b)
	{}

};

struct BarWrap : public Bar, wrapper<Bar>
{
     void v()
     {
         if (override f = this->get_override("v"))
             f();
	else
	    Bar::v();
     }

     void v2() {
	if (override f = this->get_override("v2"))
	    f();
	else
	    Foo::v2();
     }
     void default_v2()
	{
	    this->Foo::v2();
	}


     BarWrap(int a, int b=42)
	: Bar(a,b)
	{}
};

Foo::~Foo()
{}

Foo::Foo(int a_, int b_)
     : a(a_),b(b_)
{}

void Foo::showab()
{
     cout << a << " " << b << endl;
}

BOOST_PYTHON_MODULE(foo)
{
     class_<FooWrap, boost::noncopyable>("Foo",init<int,optional<int> >())
	.def("v",pure_virtual(&Foo::v))
	.def("v2",&Foo::v2, &FooWrap::default_v2)
	.def("showab",&Foo::showab);

     class_<BarWrap, bases<Foo>, boost::noncopyable 
 >("Bar",init<int,optional<int> >())
	.def("v",&Bar::v)
	.def("v2",&Foo::v2, &FooWrap::default_v2); // ***

     def("call_v",call_v);
     def("call_v2",call_v2);
}



As you see, the only way to handle this I've found is to "re-wrap" each 
virtual function in any derived class. This is rather cumbersome and 
error-prone; for example, if I forget the line marked ***, the code will 
still compile cleanly, but when call_v2 is called with a Bar-derived 
class Baz defined in Python, it will call Bar's v2 instead of Baz'.

My question therefore: is there an easier way? Ie. not having to 
redeclare and wrap every virtual function?



More information about the Cplusplus-sig mailing list