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

share|improve this question
feedback

2 Answers

up vote 7 down vote accepted

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]));
    }
}
share|improve this answer
boost::python::list can be heterogeneous, and you ahve to catch exceptions from extract. – eudoxos Aug 10 '11 at 8:08
my apologies, exception from extract will be translated to python automatically. Sorry. – eudoxos Aug 12 '11 at 12:30
yeah nice and simple to do, just the boost python documentation is so poor, and operator[] is hidden away in a template object_operators several layers up the hierarchy and not obviously an operation a list. I haven't found their website documentation any more friendly. Making len() an external method isn't as cool as they think it is either. Plus is this the only way to iterate through? – CashCow Dec 17 '12 at 11:00
feedback

To get automatic conversion from python lists, you have to define a converter, which

  1. checks if the list is convertible to your type (i.e. that it is a sequence; additionally, you can also check whether all elements are of required type, but that can be handled in the second step as well)
  2. returns the new object, if the first step succeeded; throw exception if a sequence element is not convertible to what you need.

I can't find now anything else than my code, you can copy&paste this template (it is specialized at the end of that file for various contained types).

share|improve this answer
feedback

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.