boost :: python: список Python для std :: vector - PullRequest
27 голосов
/ 21 сентября 2010

Наконец, я могу использовать std :: vector в python, используя оператор []. Хитрость заключается в том, чтобы просто предоставить контейнер в расширенной оболочке C ++, которая обрабатывает внутреннее векторное содержимое:

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

Другая проблема: как перевести списки Python в std :: vectors? Я попытался добавить класс c ++, ожидая std :: vector в качестве параметра, и добавил соответствующий код оболочки:

#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

Ответы [ 4 ]

29 голосов
/ 21 сентября 2010

Чтобы ваш метод 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]));
    }
}
23 голосов
/ 30 сентября 2013

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

#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 :: object) слишком либеральным, не стесняйтесь указывать более строгие типы (py :: list в вашем случае).*

4 голосов
/ 13 февраля 2015

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

Для примера сборки и тестового сценария Python возьмитесмотрите здесь

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

1 голос
/ 10 августа 2011

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

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

Теперь я не могу найти ничего, кроме своего кода, вы можете скопировать и вставить этот шаблон (в конце этого файла он специализирован для различных типов содержимого).

...