std :: vector для повышения :: python :: list

У меня есть метод на С ++, который вызывается из Python и должен возвращать объект списка Python.

Я уже создал метод, и он прикреплен к открытому классу и может быть вызван из python прямо сейчас ... (он возвращает void).

Итак, вопрос в том, как мне создать список Python из этого:

std::vector<std::string> results;

Я не совсем понимаю, как работает конструктор из этой документации:

http://www.boost.org/doc/libs/1_37_0/libs/python/doc/v2/list.html

Также ... Я действительно не хочу возвращать вид обернутого вектора ... Я просто хочу создать новый список Python со строковыми значениями из вектора.

Приношу свои извинения, если это дубликат ... Я нашел довольно много списков векторных вопросов, но не смог найти ни одного о создании нового списка Python.

Я мог бы расширить этот вопрос, включив в него некоторые другие вопросы, например:

Создание нового словаря Python из: std::map<std::string, std::string> и так далее.


person mcot    schedule 27.05.2011    source источник
comment
Я видел этот вопрос: stackoverflow.com/questions/3240971/ Но речь шла о возврате обернутого вектора ... Я просто хочу создать новый объект python и верни это.   -  person mcot    schedule 28.05.2011
comment
Возможный дубликат: stackoverflow.com/q/5314319/198633   -  person inspectorG4dget    schedule 10.04.2017


Ответы (6)


У меня есть эта функция, использующая итераторы для преобразования std::vector в py::list:

namespace py = boost::python;

template<class T>
py::list std_vector_to_py_list(const std::vector<T>& v)
{
    py::object get_iter = py::iterator<std::vector<T> >();
    py::object iter = get_iter(v);
    py::list l(iter);
    return l;
}
person rafak    schedule 30.05.2011
comment
нет ли у этого огромных накладных расходов? Это действительно вопрос - person Dan Niero; 02.07.2012
comment
Я пробовал это, у меня исключение на py::object iter = get_iter(v): No to_python (by-value) converter found for C++ type: class std::vector<int,class std::allocator<int> > с Boost 1.51 - person Andrew Marshall; 12.11.2012
comment
аналогично 'Не найден преобразователь to_python (по значению) для типа C ++: std :: vector ‹std :: string, std :: allocator‹ std :: string ››', boost 1.48 - person Rob Agar; 18.09.2013
comment
Та же ошибка, ‹type 'exceptions.TypeError'›: для типа C ++ не найден преобразователь to_python (по значению): std :: vector ‹double, std :: allocator ‹double›› - person SullX; 24.01.2014
comment
Здесь та же ошибка: No to_python (by-value) converter found for C++ type: std::vector<int, std::allocator<int> > - person Marcin; 05.11.2015
comment
Та же ошибка здесь с Boost 1.58. Есть идеи, как это решить? - person Hendrik Wiese; 21.03.2019

boost::python уже включает функцию упаковки векторов и карт. Вот пример кода для векторов, как вы можете видеть, списки передачи и возврата довольно просты:

// C++ code
typedef std::vector<std::string> MyList;
class MyClass {
  MyList myFuncGet();
  void myFuncSet(const Mylist& list);
  //       stuff
};

// Wrapper code

#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

using namespace boost::python;


BOOST_PYTHON_MODULE(mymodule)
{
    class_<MyList>("MyList")
        .def(vector_indexing_suite<MyList>() );

    class_<MyClass>("MyClass")
        .def("myFuncGet", &MyClass::myFuncGet)
        .def("myFuncSet", &MyClass::myFuncSet)
        ;
}

Карты очень похожи на векторы и описаны в этом сообщении: Boost :: Python - возможно автоматическое преобразование из dict - ›std :: map?

К сожалению, boost::python в настоящее время не включает средства для упаковки списков. Вы можете создать оболочку вручную, но у меня нет времени для этого ответа. Я могу выложить сегодня или завтра. Я был бы признателен за новый вопрос об этой конкретной проблеме, потому что ответ будет довольно обширным и, вероятно, выходит за рамки этого сообщения. Я бы просто избегал списков и вместо этого использовал векторы.

person Aleksey Vitebskiy    schedule 27.05.2011
comment
привет @Aleksey, думаю, у меня есть к вам связанный вопрос ссылка - person Robert Parcus; 21.07.2011
comment
Спасибо, кстати, у этого метода большие накладные расходы? Извините, я новичок в C ++ и boost.python. - person GoingMyWay; 19.08.2018
comment
А можете ли вы поделиться ссылкой на соответствующие документы vector_indexing_suite. - person GoingMyWay; 19.08.2018
comment
Все, что делает vector_indexing_suite, - это создает оболочку python для std::vector. Это означает, что доступ к std::vector осуществляется напрямую. По сути, это самые низкие накладные расходы, на которые вы можете надеяться. Вот ссылка: boost.org/doc/libs/1_68_0/libs/python/doc/html/reference/topics/. - person Aleksey Vitebskiy; 12.09.2018

Если вы хотите создать список python вручную (и чтобы функция возвращала py :: list, а не вектор), сделайте это следующим образом:

/* using namespace std; namespace py=boost::python;
   #define FOREACH BOOST_FOREACH
*/
vector<string> ss;
py::list ret;
FOREACH(const string& s, ss) ret.append(s);
return s;

Для автоматического преобразования определите преобразователь для вектора из списка Python в C ++ и из C ++ в список Python - я только что написал об этом в Создание экземпляра shared_ptr в boost :: python (вторая часть ответа); Таким образом, вы получаете действительно списки Python.

Другая возможность для автоматического преобразования (с которой у меня нет опыта) - использовать indexing_suite, который, как уже упоминал здесь коллега, обернет vector<string> как специальный класс в python.

person eudoxos    schedule 29.05.2011

Из http://gist.github.com/octavifs/5362272:

// Converts a C++ vector to a python list
template <class T>
boost::python::list toPythonList(std::vector<T> vector) {
    typename std::vector<T>::iterator iter;
    boost::python::list list;
    for (iter = vector.begin(); iter != vector.end(); ++iter) {
        list.append(*iter);
    }
    return list;
}
person o.z    schedule 07.01.2015
comment
Да, это работает, но я не уверен, слишком ли много накладных расходов из-за необходимости повторять вектор и добавлять каждый элемент. Может быть, использование массива numpy более эффективно? - person user819893; 13.02.2018

FWIW, вот шаблонная функция в том же духе, что и решение eudoxos:

namespace py = boost::python;

template<class T>
py::list std_vector_to_py_list(const std::vector<T>& v)
{
  py::list l;
  typename std::vector<T>::const_iterator it;
  for (it = v.begin(); it != v.end(); ++it)
    l.append(*it);   
  return l;  
}
person Rob Agar    schedule 18.09.2013
comment
Это копирует значения по мере добавления в список, верно? Есть ли способ избежать этого (при условии, что значения относятся к некоторому типу класса), поэтому в python get_list(0) == get_list(0) возвращает true? Что-то вроде bp::reference_existing_object, но внутри функции? - person GaryO; 06.02.2014

Я использую следующие служебные функции для преобразования из / в контейнеры stl. Тривиальная функция суммы показывает, как они используются. Также я нашел следующий пакет с открытым исходным кодом, в котором есть довольно много утилит преобразования: https://github.com/cctbx/cctbx_project/tree/master/scitbx/boost_python

#include <vector>
#include <boost/python.hpp>
#include <boost/python/object.hpp>
#include <boost/python/stl_iterator.hpp>

namespace bpy = boost::python;

namespace fm {

template <typename Container>
bpy::list stl2py(const Container& vec) {
  typedef typename Container::value_type T;
  bpy::list lst;
  std::for_each(vec.begin(), vec.end(), [&](const T& t) { lst.append(t); });
  return lst;
}

template <typename Container>
void py2stl(const bpy::list& lst, Container& vec) {
  typedef typename Container::value_type T;
  bpy::stl_input_iterator<T> beg(lst), end;
  std::for_each(beg, end, [&](const T& t) { vec.push_back(t); });
}

bpy::list sum(const bpy::list& lhs, const bpy::list& rhs) {
  std::vector<double> lhsv;
  py2stl(lhs, lhsv);

  std::vector<double> rhsv;
  py2stl(rhs, rhsv);

  std::vector<double> result(lhsv.size(), 0.0);
  for (int i = 0; i < lhsv.size(); ++i) {
    result[i] = lhsv[i] + rhsv[i];
  }
  return stl2py(result);
}

} // namespace fm

BOOST_PYTHON_MODULE(fm)
{
  bpy::def("sum", &fm::sum);
}
person Validus Oculus    schedule 25.02.2018