c++ boost-python

c++ - std:: vector para impulsar:: python:: list



boost-python (6)

Tengo un método en c ++ que recibe una llamada de python y necesita devolver un objeto de lista de python.

Ya he creado el método, y está adjunto a una clase expuesta y llamable desde Python en este momento ... (devuelve vacío).

Entonces la pregunta es, ¿cómo creo una lista de Python a partir de esto?

std::vector<std::string> results;

Realmente no entiendo cómo funciona el constructor a partir de esta documentación:

http://www.boost.org/doc/libs/1_37_0/libs/python/doc/v2/list.html

Además ... Realmente no quiero devolver el tipo de vector envuelto ... Solo quiero crear una nueva lista de python con los valores de cadena del vector.

Mis disculpas si esto es un duplicado ... Encontré bastantes listas para las preguntas del vector, pero no pude encontrar ninguna sobre la creación de una nueva lista de Python.

Podría ampliar esta pregunta para incluir algunas otras preguntas como:

Crear un nuevo diccionario de python a partir de: std::map<std::string, std::string> y así sucesivamente.


Desde http://gist.github.com/octavifs/5362272 :

// Converts a C++ vector to a python list template <class T> boost::python::list toPythonList(std::vector<T> vector) { typename std::vector<T>::iterator iter; boost::python::list list; for (iter = vector.begin(); iter != vector.end(); ++iter) { list.append(*iter); } return list; }


FWIW, aquí hay una función de plantilla en la misma línea que la solución de eudoxos:

namespace py = boost::python; template<class T> py::list std_vector_to_py_list(const std::vector<T>& v) { py::list l; typename std::vector<T>::const_iterator it; for (it = v.begin(); it != v.end(); ++it) l.append(*it); return l; }


Si solo desea crear una lista de python de forma manual (y hacer que la función devuelva py :: list en lugar de vector), hágalo así:

/* using namespace std; namespace py=boost::python; #define FOREACH BOOST_FOREACH */ vector<string> ss; py::list ret; FOREACH(const string& s, ss) ret.append(s); return s;

Para las conversiones automáticas, defina el convertidor para el vector de la lista de python a c ++ y de la lista c ++ a python. Acabo de escribir sobre esto en Instanciando shared_ptr en boost :: python (la segunda parte de la respuesta); de esa manera, obtienes listas realmente de pitones.

Otra posibilidad para la conversión automática (con la que no tengo experiencia) es usar indexing_suite, que ajustará vector<string> como una clase especial en python, como ya mencionó un colega aquí.


Tengo esta función usando iteradores para convertir std::vector a py::list :

namespace py = boost::python; template<class T> py::list std_vector_to_py_list(const std::vector<T>& v) { py::object get_iter = py::iterator<std::vector<T> >(); py::object iter = get_iter(v); py::list l(iter); return l; }


Utilizo las siguientes funciones de utilidad para convertir contenedores de / a stl. La función de suma trivial ilustra cómo se usan. También encontré el siguiente paquete opensource que tiene bastantes utilidades de conversión: https://github.com/cctbx/cctbx_project/tree/master/scitbx/boost_python

#include <vector> #include <boost/python.hpp> #include <boost/python/object.hpp> #include <boost/python/stl_iterator.hpp> namespace bpy = boost::python; namespace fm { template <typename Container> bpy::list stl2py(const Container& vec) { typedef typename Container::value_type T; bpy::list lst; std::for_each(vec.begin(), vec.end(), [&](const T& t) { lst.append(t); }); return lst; } template <typename Container> void py2stl(const bpy::list& lst, Container& vec) { typedef typename Container::value_type T; bpy::stl_input_iterator<T> beg(lst), end; std::for_each(beg, end, [&](const T& t) { vec.push_back(t); }); } bpy::list sum(const bpy::list& lhs, const bpy::list& rhs) { std::vector<double> lhsv; py2stl(lhs, lhsv); std::vector<double> rhsv; py2stl(rhs, rhsv); std::vector<double> result(lhsv.size(), 0.0); for (int i = 0; i < lhsv.size(); ++i) { result[i] = lhsv[i] + rhsv[i]; } return stl2py(result); } } // namespace fm BOOST_PYTHON_MODULE(fm) { bpy::def("sum", &fm::sum); }


boost::python ya incluye funcionalidad para envolver vectores y mapas. Aquí hay un código de muestra para los vectores, ya que puedes ver las listas de aprobación y devolución es bastante simple:

// C++ code typedef std::vector<std::string> MyList; class MyClass { MyList myFuncGet(); void myFuncSet(const Mylist& list); // stuff }; // Wrapper code #include <boost/python/suite/indexing/vector_indexing_suite.hpp> using namespace boost::python; BOOST_PYTHON_MODULE(mymodule) { class_<MyList>("MyList") .def(vector_indexing_suite<MyList>() ); class_<MyClass>("MyClass") .def("myFuncGet", &MyClass::myFuncGet) .def("myFuncSet", &MyClass::myFuncSet) ; }

Los mapas son muy similares a los vectores y se describen en esta publicación: Boost :: Python: ¿es posible convertir automáticamente dict -> std :: map?

Desafortunadamente boost::python no incluye actualmente instalaciones para listas de embalaje. Puedes crear el contenedor manualmente, pero estoy fuera de tiempo por esta respuesta. Puedo publicarlo hoy o mañana. Apreciaría una nueva pregunta sobre este problema en particular, porque la respuesta será bastante extensa y probablemente esté fuera del alcance de esta publicación. Solo evitaría listas y usar vectores en su lugar.