Reputation: 2372
I have two virtual classes I would like to wrap in boost python, I want to be able to write Python class that extends them. The thing is, one of the classes has a method that return a reference of the other class, and I can't figure how to do.
Here is a simplified version of code of class to be wrapped.
class Foo
{
public:
virtual ~Foo() {}
virtual int a() = 0;
};
class Bar
{
public:
virtual ~Bar() {}
virtual Foo const& b() = 0;
};
So I started wrapping about this way.
class FooWrap : public Foo, public wrapper<Foo>
{
public:
int a()
{
return this->get_override("a")();
}
};
class BarWrap : public Bar, public wrapper<Bar>
{
public:
Foo const& b()
{
return this->get_override("b")();
}
};
BOOST_PYTHON_MODULE(foobar)
{
class_<FooWrap, boost::noncopyable>("Foo")
.def("a", pure_virtual(&Foo::a))
;
class_<BarWrap, boost::noncopyable>("Bar")
.def("b", pure_virtual(&Bar::b))
;
}
And I get a compile error about "cannot instantiate abstract class [...] pure virtual function was not defined" "see declaration of 'foo::a'"
Upvotes: 3
Views: 3045
Reputation: 774
The following code compiles for me. Inside your python Bar subclass you should be able to return a Foo instance from the b method.
#include <boost/python.hpp>
class Foo
{
public:
virtual ~Foo() {}
virtual int a() = 0;
};
class Bar
{
public:
virtual ~Bar() {}
virtual Foo const& b() = 0;
};
class FooWrap : public Foo, public boost::python::wrapper<Foo>
{
public:
int a()
{
return this->get_override("a")();
}
};
class BarWrap : public Bar, public boost::python::wrapper<Bar>
{
public:
Foo const& b()
{
return this->get_override("b")();
}
};
BOOST_PYTHON_MODULE(foobar)
{
boost::python::class_<FooWrap, boost::noncopyable>("Foo")
.def("a", boost::python::pure_virtual(&Foo::a)) ;
boost::python::class_<BarWrap, boost::noncopyable>("Bar")
.def("b", boost::python::pure_virtual(&Bar::b), boost::python::return_internal_reference<>());
}
Upvotes: 3
Reputation: 5344
I've been able to compile and run your code after I added call policy for Bar::b
function:
BOOST_PYTHON_MODULE(foobar)
{
class_<FooWrap, boost::noncopyable>("Foo")
.def("a", pure_virtual(&Foo::a));
class_<BarWrap, boost::noncopyable>("Bar")
.def("b", pure_virtual(&Bar::b),
return_internal_reference<>());
}
Basically, it's just means that lifetime of returned reference from Bar::b
should be dependent on lifetime of Bar
instance. You can read about call policies in boost docs.
What compiler and boost version are you using? I've got the following descriptive error with boost 1.46.0 and gcc 4.6.1:
error: no match for call to ‘(const boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<const Foo&>) (const Foo&)’
Upvotes: 4