2010-07-13 4 views
1

Je suis nouveau sur python, j'ai regardé boost python, et il semble très impressionnant. Cependant en passant par l'introduction je ne peux pas trouver des exemples où, le vecteur d'objets sont retournés comme python list/tuples.boost python supporte une fonction retournant un vecteur, par ref ou value?

i.e Prenons cet exemple, je veux exposer la classe X, Cont et toutes ses fonctions. peu critique étant un vecteur de retour des X ou des chaînes à python

class X {}; 

    class Cont { 

     ..... 
     // how can this be exposed using boost python 
     const std::vector<X>& const_ref_x_vec() const { return x_vec_;} 
     std::vector<X> value_x_vec() const { return x_vec;} 

     const std::vector<std::string>& const_ref_str_vec() const { return str_vec_;} 
     std::vector<std::string> value_str_vec() const { return str_vec_; } 

     ... 
    private: 
     std::vector<X> x_vec_; 
     std::vector<std::string> str_vec_; 
    }; 

Ma tentative infructueuse à essayer d'exposer les fonctions comme const_ref_x_vec(), value_x_vec(), etc conduit juste des erreurs de compilation. De googling around Je n'ai vu aucun exemple supportant des vecteurs retournés par valeur ou référence. Est-ce encore possible avec boost python? y a-t-il des solutions de contournement? devrais-je utiliser SWIG pour ce cas?

Toute aide appréciée.

Avtar

Répondre

2

Parce que vous ne pouvez pas exposer les types de modèle à python vous devez exposer explicitement chaque type de vecteur que vous voulez utiliser, par exemple, cela est de mon code:

modèle générique pour envelopper choses:

namespace bp = boost::python; 

inline void IndexError(){ 
    PyErr_SetString(PyExc_IndexError, "Index out of range"); 
    bp::throw_error_already_set(); 
} 

template<class T> 
struct vec_item{ 
    typedef typename T::value_type V; 
    static V& get(T& x, int i){ 
     static V nothing; 
     if(i < 0) i += x.size(); 
     if(i >= 0 && i < int(x.size())) return x[i]; 
     IndexError(); 
     return nothing; 
    } 
    static void set(T& x, int i, V const& v){ 
     if(i < 0) i += x.size(); 
     if(i >= 0 && i < int(x.size())) x[i] = v; 
     else IndexError(); 
    } 
    static void del(T& x, int i){ 
     if(i < 0) i += x.size(); 
     if(i >= 0 && i < int(x.size())) x.erase(x.begin() + i); 
     else IndexError(); 
    } 
    static void add(T& x, V const& v){ 
     x.push_back(v); 
    } 
}; 

Ensuite, pour chaque conteneur:

// STL Vectors: 
    // LineVec 
    bp::class_< std::vector<Line> >("LineVec") 
     .def("__len__", &std::vector<Line>::size) 
     .def("clear", &std::vector<Line>::clear) 
     .def("append", &vec_item< std::vector<Line> >::add, 
       bp::with_custodian_and_ward<1, 2>()) // let container keep value 
     .def("__getitem__", &vec_item< std::vector<Line> >::get, 
      bp::return_value_policy<bp::copy_non_const_reference>()) 
     .def("__setitem__", &vec_item< std::vector<Line> >::set, 
      bp::with_custodian_and_ward<1,2>()) // to let container keep value 
     .def("__delitem__", &vec_item< std::vector<Line> >::del) 
     .def("__iter__", bp::iterator< std::vector<Line> >()) 
    ; 
    // ... 

Une approche similaire est possible pour std::map. J'ai utilisé beaucoup d'aide de wiki.python.org en écrivant ceci.

8

La raison de l'Autopulated était essentiellement correcte, mais le code était plus compliqué que nécessaire.

Le vector_indexing_suite peut faire tout ce travail pour vous:

class_< std::vector<X> >("VectorOfX") 
    .def(vector_indexing_suite< std::vector<X> >()) 
    ; 

Il y a un map_indexing_suite aussi bien.

Questions connexes