Our group is developing a numeric framework using C++. We whould now like to wrap basic parts of our framework to be available in Python. Our weapon of choice is Boost.Python since we're already Boost for other purposes as well. We solely use smart_ptrs to support polymorphism. The following snippet is a simple example of how we would apply the strategy pattern:
#include <boost/shared_ptr.hpp>
struct AbsStrategy
{
virtual std::string talk( ) = 0;
};
typedef boost::shared_ptr<AbsStrategy> StrategyPtr;
struct Foo : AbsStrategy
{
std::string talk( )
{
return "I am a Foo!";
}
};
struct Bar : AbsStrategy
{
std::string talk( )
{
return "I am a Bar!";
}
};
struct Client
{
Client( StrategyPtr strategy ) :
myStrategy( strategy )
{
}
bool checkStrategy( StrategyPtr strategy )
{
return ( strategy == myStrategy );
}
StrategyPtr myStrategy;
};
If I wrap the whole thing using Boost.Python like so
#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE( BoostPython )
{
class_<Foo>( "Foo" )
.def( "talk", &Foo::talk );
class_<Bar>( "Bar" )
.def( "talk", &Bar::talk );
class_<Client>( "Client", init<StrategyPtr>( ) )
.def( "checkStrategy", &Client::checkStrategy );
}
the following warning pops up during compilation
C:/boost/include/boost-1_51/boost/python/object/instance.hpp:14:36: warning: type attributes ignored after type is already defined [-Wattributes]
When I try to use wrappers in python, I get the following errors
>>> from BoostPython import *
>>> foo = Foo()
>>> bar = Bar()
>>> client = Client(foo)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
Tree.__init__(Tree, Foo)
did not match C++ signature:
__init__(_object*, boost::shared_ptr<AbsStrategy>)
>>> client = Client(bar)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
Tree.__init__(Tree, Bar)
did not match C++ signature:
__init__(_object*, boost::shared_ptr<AbsStrategy>)
What is missing to make the whole thing work without changing our framework? The wrappers can be adapted freely of course.
Ok I found the solution. One has to use implicitly_convertible
in the module declaration as shown below.
#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE( BoostPython )
{
class_<Foo>( "Foo" )
.def( "talk", &Foo::talk );
class_<Bar>( "Bar" )
.def( "talk", &Bar::talk );
class_<Client>( "Client", init<StrategyPtr>( ) )
.def( "checkStrategy", &Client::checkStrategy );
implicitly_convertible<boost::shared_ptr<Foo> , StrategyPtr>();
implicitly_convertible<boost::shared_ptr<Bar> , StrategyPtr>();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With