2010-05-13 5 views
15

J'ai commencé à jouer un peu avec boost python et j'ai rencontré un problème. J'ai essayé d'exposer une classe C++ à python qui ne posait aucun problème. Mais je ne peux pas sembler réussir à implémenter la fonctionnalité __str__ pour la classe sans avoir des erreurs de compilation que je ne comprends pas. J'utilise boost 1_42 prebuild de boostpro. Je construis la bibliothèque en utilisant cmake et le compilateur vs2010.Problèmes de construction lors de l'ajout de la méthode `__str__` à Boost Python classe C++

J'ai une configuration très simple. L'en-tête fichier (tutorial.h) se présente comme suit:

#include <iostream> 
namespace TestBoostPython{ 
    class TestClass { 
     private: 
      double m_x; 
     public: 
      TestClass(double x); 
      double Get_x() const; 
      void Set_x(double x); 
    }; 
    std::ostream &operator<<(std::ostream &ostr, const TestClass &ts); 
}; 

et le cpp-fichier correspondant ressemble à:

#include <boost/python.hpp> 
#include "tutorial.h" 

using namespace TestBoostPython; 

TestClass::TestClass(double x) 
{ 
    m_x = x; 
} 

double TestClass::Get_x() const 
{ 
    return m_x; 
} 
void TestClass::Set_x(double x) 
{ 
    m_x = x; 
} 

std::ostream &operator<<(std::ostream &ostr, const TestClass &ts) 
{ 
    ostr << ts.Get_x() << "\n"; 
    return ostr; 
} 

BOOST_PYTHON_MODULE(testme) 
{ 
using namespace boost::python; 
class_<TestClass>("TestClass", init<double>()) 
    .add_property("x", &TestClass::Get_x, &TestClass::Set_x) 
    .def(str(self)) 
    ; 
} 

Le CMakeLists.txt se présente comme suit:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 

project (testme) 

FIND_PACKAGE(Boost REQUIRED) 
FIND_PACKAGE(Boost COMPONENTS python REQUIRED) 
FIND_PACKAGE(PythonLibs REQUIRED) 

set(Boost_USE_STATIC_LIBS OFF) 
set(Boost_USE_MULTITHREAD ON) 

INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) 
INCLUDE_DIRECTORIES (${PYTHON_INCLUDE_PATH}) 

add_library(testme SHARED tutorial.cpp) 
target_link_libraries(testme ${Boost_PYTHON_LIBRARY}) 
target_link_libraries(testme ${PYTHON_LIBRARY} 

l'erreur de compilation que je reçois est la suivante:

Compiling... 
tutorial.cpp 
    C:\Program Files (x86)\boost\boost_1_42\boost/python/def_visitor.hpp(31) : error C2780: 'void boost::python::api::object_operators::visit(ClassT &,const char *,const boost::python::detail::def_helper &) const' : expects 3 arguments - 1 provided 
    with 
    [ 
     U=boost::python::api::object 
    ] 
    C:\Program Files (x86)\boost\boost_1_42\boost/python/object_core.hpp(203) : see declaration of 'boost::python::api::object_operators::visit' 
    with 
    [ 
     U=boost::python::api::object 
    ] 
    C:\Program Files (x86)\boost\boost_1_42\boost/python/def_visitor.hpp(67) : see reference to function template instantiation 'void boost::python::def_visitor_access::visit,classT>(const V &,classT &)' being compiled 
    with 
    [ 
     DerivedVisitor=boost::python::api::object, 
     classT=boost::python::class_, 
     V=boost::python::def_visitor 
    ] 
    C:\Program Files (x86)\boost\boost_1_42\boost/python/class.hpp(225) : see reference to function template instantiation 'void boost::python::def_visitor::visit>(classT &) const' being compiled 
    with 
    [ 
     DerivedVisitor=boost::python::api::object, 
     W=TestBoostPython::TestClass, 
     classT=boost::python::class_ 
    ] 
    .\tutorial.cpp(29) : see reference to function template instantiation 'boost::python::class_ &boost::python::class_::def(const boost::python::def_visitor &)' being compiled 
    with 
    [ 
     W=TestBoostPython::TestClass, 
     U=boost::python::api::object, 
     DerivedVisitor=boost::python::api::object 
    ] 

Est-ce que quelqu'un a une idée de ce qui s'est passé? Si je supprime la partie .def (str (self)) du code de l'encapsuleur, tout se compile bien et la classe est utilisable depuis python. Je serais très reconnaissant pour l'aide.

Merci, Rickard

modifier: oublièrent un const

+0

Nice! Je n'ai pas regardé d'abord avec attention et j'ai défini l'opérateur << dans la classe elle-même plutôt que dans l'espace de noms comme vous l'avez fait, ce qui a fait toute la différence pour appeler print (myObj) en Python. Beau travail Rickard. Cependant j'ai remarqué que j'ai encore besoin d'appeler explicitement print pour que mon objet soit rendu comme je le souhaite en python. Si je viens d'entrer dans mon objet, il retourne les résultats comme si j'appelais type (myObj), ce qui peut être un comportement par défaut pour Python, peut-être que je suis mélangé avec l'expérience dans R ou Matlab. – jxramos

Répondre

24

J'ai récemment rencontré ce problème; La solution qui a fonctionné était de résoudre explicitement l'str et self sur cette ligne:

.def(str(self)) 

Alors qu'il devient:

.def(self_ns::str(self_ns::self)) 

Je ne sais pas pourquoi cela est nécessaire, (savoir quelque chose la complication de résolution de surcharge qui se passe dans boost python, c'est probablement quelque chose là ...) mais ça a fonctionné pour moi :)

+2

Merveilleux! Merci beaucoup. J'adore boost :: python mais quand ça se passe comme ça, je pense qu'il serait peut-être plus simple d'emballer l'objet dans Python C-API. Je n'aurais jamais trouvé cette solution par moi-même. Merci encore. – Rickard

+0

Cela a toujours fonctionné pour moi aujourd'hui. Je me demande si cela n'aurait pas dû être réglé depuis longtemps ...? – varantir

+0

Il y a un boost :: python :: str, et un boost :: python :: self_ns :: str, qui sont des choses très différentes. Ceci est nécessaire car si votre code utilise 'boost :: python' (ce qui sera probablement le cas), le compilateur trouvera le précédent, ce qui le rend très confus. – stochastic

10

Je suis tombé sur la même chose. Ajout de cette ligne (au lieu de qualifier str et self) fonctionne également:

using self_ns::str; 
Questions connexes