Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::python: Python list to std::vector

Finally I'm able to use std::vector in python using the [] operator. The trick is to simple provide a container in the boost C++ wrapper which handles the internal vector stuff:

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

The other challenge is: Howto translate python lists into std::vectors? I tried to add a c++ class expecting a std::vector as parameter and added the corresponding wrapper code:

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

But if doing so, I end up with the following 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> >) 

Can anybody tell me how I can access python lists within my c++ function?

Thanks, Daniel

like image 231
dmorlock Avatar asked Sep 21 '10 14:09

dmorlock


2 Answers

To make your C++ method accept Python lists you should use boost::python::list

void massadd(boost::python::list& ns) {     for (int i = 0; i < len(ns); ++i)     {         add(boost::python::extract<double>(ns[i]));     } } 
like image 188
Arlaharen Avatar answered Oct 05 '22 09:10

Arlaharen


Here's what I use:

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

Should you find the input type (py::object) too liberal, feel free to specify stricter types (py::list in your case).

like image 36
rdesgroppes Avatar answered Oct 05 '22 08:10

rdesgroppes