2010-09-21 15 views
20

Finalmente sono in grado di usare std :: vector in python usando l'operatore []. Il trucco è quello di fornire un contenitore semplice nella confezione spinta C++ che gestisce la roba vettore interna:boost :: python: Python lista a std :: vector

#include <boost/python.hpp> 
#include <vector> 
class world 
{ 
    std::vector<double> myvec; 

    void add(double n) 
    { 
     this->myvec.push_back(n); 
    } 

    std::vector<double> show() 
    { 
    return this->myvec; 
    } 
}; 

BOOST_PYTHON_MODULE(hello) 
{ 
    class_<std::vector<double> >("double_vector") 
     .def(vector_indexing_suite<std::vector<double> >()) 
    ; 

    class_<World>("World") 
    .def("show", &World::show) 
     .def("add", &World::add) 
    ; 
} 

L'altra sfida è: Come tradurre liste pitone in std :: vettori? Ho provato ad aggiungere una classe C++ in attesa di uno std :: vector come parametro e aggiunto il codice wrapper corrispondente:

#include <boost/python.hpp> 
#include <vector> 
class world 
{ 
    std::vector<double> myvec; 

    void add(double n) 
    { 
     this->myvec.push_back(n); 
    } 

    void massadd(std::vector<double> ns) 
    { 
     // Append ns to this->myvec 
    } 

    std::vector<double> show() 
    { 
    return this->myvec; 
    } 
}; 

BOOST_PYTHON_MODULE(hello) 
{ 
    class_<std::vector<double> >("double_vector") 
     .def(vector_indexing_suite<std::vector<double> >()) 
    ; 

    class_<World>("World") 
    .def("show", &World::show) 
     .def("add", &World::add) 
     .def("massadd", &World::massadd) 
    ; 
} 

Ma se così facendo, io alla fine con il seguente Boost.Python.ArgumentError:

>>> w.massadd([2.0,3.0]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Boost.Python.ArgumentError: Python argument types in 
    World.massadd(World, list) 
did not match C++ signature: 
    massadd(World {lvalue}, std::vector<double, std::allocator<double> >) 

Qualcuno può dirmi come posso accedere alle liste python all'interno della mia funzione C++?

Grazie, Daniel

risposta

23

Per rendere il vostro metodo di C++ accetta Python elenca si dovrebbe usare boost::python::list

void massadd(boost::python::list& ns) 
{ 
    for (int i = 0; i < len(ns); ++i) 
    { 
     add(boost::python::extract<double>(ns[i])); 
    } 
} 
+0

'boost :: python :: list' può essere eterogeneo, e devi raccogliere eccezioni da' extract'. – eudoxos

+0

mi scuso, l'eccezione da 'extract' sarà tradotta automaticamente in python. Scusate. – eudoxos

+4

sì bello e semplice da fare, solo la documentazione di boost python è così scarsa, e l'operatore [] è nascosto in un modello object_operators diversi livelli nella gerarchia e non è ovviamente un'operazione un elenco. Non ho trovato la loro documentazione del sito web più amichevole. Fare len() un metodo esterno non è così bello come pensano che sia. Plus è questo l'unico modo per scorrere? – CashCow

1

Per ottenere la conversione automatica dalle liste Python, è necessario definire un convertitore, che

  1. controlla se l'elenco è convertibile per il tipo (vale a dire che si tratta di una sequenza; inoltre, è anche possibile controllare se tutti gli elementi sono di ri tipo richiesto, ma che può essere gestito anche nella seconda fase)
  2. restituisce il nuovo oggetto, se il primo passaggio è riuscito; genera un'eccezione se un elemento sequenza non è convertibile in base alle esigenze.

non riesco a trovare ora altro che il mio codice, è possibile copiare & incollare this template (è specializzata alla fine di quel file di vari tipi contenute).

17

Ecco quello che uso:

#include <boost/python/stl_iterator.hpp> 

namespace py = boost::python; 

template< typename T > 
inline 
std::vector<T> to_std_vector(const py::object& iterable) 
{ 
    return std::vector<T>(py::stl_input_iterator<T>(iterable), 
          py::stl_input_iterator<T>()); 
} 

si dovrebbe trovare il tipo di ingresso (pi :: oggetto) troppo liberale, sentitevi liberi di specificare i tipi più severi (py :: lista nel tuo caso).

3

Sulla base delle risposte di cui sopra ho creato un esempio di accesso liste Python in C++, nonché la restituzione di un elenco di pitone da una funzione C++:

#include <boost/python.hpp> 
#include <string> 

namespace py = boost::python; 

// dummy class 
class drow{ 
    public: 
     std::string word; 
     drow(py::list words); 
     py::list get_chars(); 
}; 

// example of passing python list as argument (to constructor) 
drow::drow(py::list l){ 
    std::string w; 
    std::string token; 
    for (int i = 0; i < len(l) ; i++){ 
     token = py::extract<std::string>(l[i]); 
     w += token; 
    } 
    this -> word = w; 
} 

// example of returning a python list 
py::list drow::get_chars(){ 
    py::list char_vec; 
    for (auto c : word){ 
     char_vec.append(c); 
    } 
    return char_vec; 
} 

// binding with python 
BOOST_PYTHON_MODULE(drow){ 
    py::class_<drow>("drow", py::init<py::list>()) 
     .def("get_chars", &drow::get_chars); 
} 

Per un esempio di compilazione e di uno script python test di dare un'occhiata here

Grazie Arlaharen & rdesgroppes per i puntatori (gioco di parole non previsto).

Problemi correlati