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>
и т.д.
Ответы
Ответ 1
У меня есть эта функция, используя итераторы для преобразования 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;
}
Ответ 2
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 → станд:: карта?
К сожалению, boost::python
в настоящее время не включает средства для упаковки списков. Вы можете создать обертку вручную, но мне не хватает времени для ответа. Я могу опубликовать его сегодня или завтра. Я был бы признателен за новый вопрос об этой конкретной проблеме, потому что ответ будет довольно обширным и, вероятно, выходит за рамки этой публикации. Я бы просто избегал списков и использовал векторы.
Ответ 3
Если вы хотите только создать список 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 в С++ и из С++ в список python - я только что написал об этом в Создание экземпляров shared_ptr в boost:: python (вторая часть ответа); Таким образом, вы получаете реальные списки python.
Еще одна возможность автоматического преобразования (с которой у меня нет опыта) заключается в использовании indexing_suite, который обернет vector<string>
в качестве специального класса в python, как уже упоминал коллега.
Ответ 4
Из 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;
}
Ответ 5
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;
}
Ответ 6
Я использую следующие функции утилиты для преобразования из/в 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);
}