2010-09-21 4 views
20

Наконец, я могу использовать std :: vector в python с помощью оператора []. Хитрость заключается в том, чтобы просто предоставить контейнер в обертке подталкивание C++, который обрабатывает внутренний вектор материал:boost :: python: список Python для 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) 
    ; 
} 

Другой проблемой является: Howto перевести списки питона в StD :: векторы? Я пытался добавить класс C++, ожидая зЬй :: вектора в качестве параметра и добавлен соответствующий код обертки:

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

Но если это так, я в конечном итоге со следующим 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> >) 

Может ли кто-нибудь сказать мне, как я могу получить доступ к спискам python в моей функции C++?

Спасибо, Daniel

ответ

23

Для того, чтобы ваш метод C++ принимает Python список, вы должны использовать 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' может быть гетерогенным, и вы можете получить исключения из' extract'. – eudoxos

+0

мои извинения, исключение из 'extract' будет автоматически переведено на python. Сожалею. – eudoxos

+4

Да, хорошо и просто сделать, просто документация по boost python настолько бедна, и оператор [] скрыт в шаблоне object_operators несколькими слоями вверх по иерархии и, очевидно, не является операцией списка. Я еще не нашел их документацию на сайте более дружелюбной. Создание len() внешнего метода не так круто, как кажется. Плюс это единственный способ пройти через итерацию? – CashCow

1

Чтобы получить автоматическое преобразование из списков питона, вы должны определить, конвертер, который

  1. проверяет, является ли список конвертируемым для вашего типа (т. Е. Что это последовательность, кроме того, вы также можете проверить, все ли элементы но который может быть обработан и на втором этапе)
  2. возвращает новый объект, если первый шаг преуспел; исключение, если элемент последовательности не конвертируется в то, что вам нужно.

Я не могу сейчас найти ничего, кроме моего кода, вы можете скопировать & пасту this template (она специализируется в конце этого файла для различных типов Содержится).

17

Вот что я использую:

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

Если вы нашли тип входа (р :: объект) слишком либеральный, не стесняйтесь задать более строгие тип (Py :: список в вашем случае).

3

На основании приведенных выше ответов, которые я создал пример доступа списки питона в 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); 
} 

Для примера построения и питон скрипта теста посмотрит here

спасибо Arlaharen & rdesgroppes для указателей (каламбур не предназначен).

Смежные вопросы