10

How do I pass a Python list of my object type ClassName to a C++ function that accepts a vector<ClassName>?

The best I found is something like this: example. Unfortunately, the code crashes and I can't seem to figure out why. Here's what I used:

template<typename T>
void python_to_vector(boost::python::object o, vector<T>* v) {
    try {
      object iter_obj = object(handle<>(PyObject_GetIter(o.ptr())));
      return;
      for (;;) {
          object obj = extract<object>(iter_obj.attr("next")());
          // Should launch an exception if it cannot extract T
          v->emplace_back(extract<T>(obj));
      }
    } catch(error_already_set) {
        PyErr_Clear();
        // If there is an exception (no iterator, extract failed or end of the
        // list reached), clear it and exit the function
        return;
    }
}
Neil G
  • 32,138
  • 39
  • 156
  • 257

2 Answers2

14

Assuming you have function that takes a std::vector<Foo>

void bar (std::vector<Foo> arg)

The easiest way to handle this is to expose the vector to python.

BOOST_PYTHON_MODULE(awesome_module)
{
    class_<Foo>("Foo")
        //methods and attrs here
    ;

    class_<std::vector<Foo> >("VectorOfFoo")
        .def(vector_indexing_suite<std::vector<foo> >() )
    ;

    .def("bar", &bar)
}

So now in python we can stick Foos into a vector and pass the vector to bar

from awesome_module import *
foo_vector = VectorOfFoo()
foo_vector.extend(Foo(arg) for arg in arglist)
bar(foo_vector)
Matthew Scouten
  • 15,303
  • 9
  • 33
  • 50
  • Thank you very much. Is there a way to have the conversion from list to vector automatic? – Neil G Jan 29 '11 at 18:34
  • Unfortunately, no. You can, however, have a function written on the python side that takes a list, converts it to a vector, and passes it on to the bar function. That will help hide the c++ ugliness a little. – Matthew Scouten Feb 07 '11 at 20:09
3

Found an iterator that solves my problem:

#include <boost/python/stl_iterator.hpp>
template<typename T>
void python_to_vector(boost::python::object o, vector<T>* v) {
    stl_input_iterator<T> begin(o);
    stl_input_iterator<T> end;
    v->clear();
    v->insert(v->end(), begin, end);
}
Neil G
  • 32,138
  • 39
  • 156
  • 257
  • It would be much easier to do this work on the python side. Just wrap the vector using vector_indexing_suite, and add what ever you need to in python, before handing it to c++ – Matthew Scouten Jan 28 '11 at 15:15
  • @Matthew: Would you mind adding an answer? I don't know what you mean. – Neil G Jan 28 '11 at 19:26