2010-09-21 15 views
20

Finalmente puedo usar std :: vector en python usando el operador []. El truco es sencillo proporcionar un recipiente en el envoltorio impulso C++ que maneja el material de vectores internos:boost :: python: lista de Python 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) 
    ; 
} 

El otro reto es: CÓMO de traducir las listas de Python en std :: vectores? He intentado añadir una clase de C++ esperando un std :: vector como parámetro y añadido el código de contenedor correspondiente:

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

Pero si al hacerlo, termino con la siguiente 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> >) 

¿Alguien puede decirme cómo puedo acceder a las listas de Python dentro de mi función C++?

Gracias, Daniel

Respuesta

23

Para hacer que su método C++ aceptar Python enumera debería utilizar 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' puede ser heterogéneo, y usted debe detectar excepciones de' extract'. – eudoxos

+0

mis disculpas, la excepción de 'extract' se traducirá automáticamente a python. Lo siento. – eudoxos

+4

sí, fácil y simple de hacer, solo la documentación de boost python es tan pobre, y el operador [] está escondido en una plantilla object_operators varias capas en la jerarquía y no obviamente una lista de operaciones. No he encontrado la documentación de su sitio web más amigable. Hacer len() un método externo no es tan genial como creen que es. Además, ¿es esta la única forma de iterar? – CashCow

1

Para obtener la conversión automática de las listas de pitón, usted tiene que definir un convertidor, que

  1. comprueba si la lista es convertible a su tipo (es decir, que es una secuencia, además, también puede verificar si todos los elementos son de tipo requerido, pero que se puede manejar en el segundo paso también)
  2. devuelve el nuevo objeto, si el primer paso fue exitoso; lanzar una excepción si un elemento de secuencia no es convertible a lo que necesita.

no puedo encontrar ahora otra cosa que mi código, puede copiar & pasta this template (que está especializada en el final de ese archivo para diversos tipos contenidos).

17

Esto es lo que yo 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>()); 
} 

En caso de encontrar el tipo de entrada (py :: objeto) demasiado liberal, no dude en especificar los tipos más estrictas (PY :: lista en su caso).

3

Sobre la base de las respuestas anteriores que he creado un ejemplo de acceso a las listas de Python en C++, así como devolver una lista de pitón de una función de 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); 
} 

Para un ejemplo de construcción y un script en Python prueba de echar un vistazo here

Gracias Arlaharen & rdesgroppes para los punteros (juego de palabras no previsto).

Cuestiones relacionadas