2013-01-22 13 views
5

Nasza grupa rozwija framework numeryczny używając C++. Teraz chcielibyśmy owijać podstawowe części naszego frameworku, aby były dostępne w Pythonie. Nasza ulubiona broń to Boost.Python, ponieważ jesteśmy już Boost do innych celów. Używamy wyłącznie smart_ptrs do wspierania polimorfizmu. Poniższy urywek jest prostym przykładem tego, jak chcemy zastosować wzorzec strategii:Używanie shared_ptr do abstrakcyjnej podstawy jako właściciela z boost.python

#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; 
}; 

Gdybym zawinąć całość przy użyciu Boost.Python jak tak

#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); 
} 

następujące ostrzeżenie wyskakuje podczas kompilacji

C:/boost/include/boost-1_51/boost/python/object/instance.hpp:14:36: warning: type attributes ignored after type is already defined [-Wattributes] 

Kiedy próbuję użyć owijarki w Pythonie, otrzymuję następujące błędy

>>> 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>) 

Czego brakuje, aby wszystko działało bez zmiany naszego systemu? Opakowania można oczywiście swobodnie przystosować.

+0

Jeśli nie otrzymasz odpowiedzi tutaj, spróbuj listy dyskusyjnej Boost.Python, gmane.comp.python.C++. – user763305

Odpowiedz

4

Ok Znalazłem rozwiązanie. Należy użyć implicitly_convertible w deklaracji modułu, jak pokazano poniżej.

#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>(); 
}