обертывание списка структур с помощью boost.python

У меня есть функция C ++, которая возвращает список структур. Внутри структуры больше списков структур.

struct CameraInfo { CamName name; std::list<CamImageFormat> lImgFormats; std::list<CamControls> lCamControls; }; std::list<CameraInfo> getCameraInfo() { std::list<CameraInfo> lCamerasInfo; // fill lCamerasInfo return lCamerasInfo; } 

то для экспорта я использовал:

 class_<CameraNode....> >("CameraNode", no_init) ... ... .def("listCameraInfo", make_function(&CameraNode::listCameraInfo)) .staticmethod("listCameraInfo") ... ; 

И это было нормально, так как я использовал cout для печати данных на экране … Я хотел бы теперь использовать возвращаемое значение и его содержимое из свойств, подобных python, таким образом:

 cameras = [] cameras = CameraNode.getCameraInfo() print cameras[0].name print cameras[0].lImgFormats[0] and so on... 

Возможно ли это? Должен ли я использовать add_property вместо этого? Я не думаю, что могу создать класс для каждой структуры. Этот дизайн имел смысл, когда я работал только на C ++, но теперь, когда мне придется его обернуть, я все больше запутался.

Любые советы по упаковке std :: list с boost.python в общем случае были бы очень хорошо приняты.

Редактировать:

Я добавлю ссылки, которые я нашел полезными: Итераторы StlContainers

2 Solutions collect form web for “обертывание списка структур с помощью boost.python”

Должен ли он быть std::list ? Если вы используете std::vector вы можете использовать boost::python::vector_indexing_suite чтобы обернуть список. Подробнее см. В этом сообщении .

Если вы должны использовать std::list вам нужно создать вспомогательный класс, который обертывает функцию std::list с помощью методов list python. Это может быть довольно сложным, но выполнимым.

std_item.hpp:

 #include <list> #include <algorithm> #include <boost/python.hpp> template<class T> struct listwrap { typedef typename T::value_type value_type; typedef typename T::iterator iter_type; static void add(T & x, value_type const& v) { x.push_back(v); } static bool in(T const& x, value_type const& v) { return std::find(x.begin(), x.end(), v) != x.end(); } static int index(T const& x, value_type const& v) { int i = 0; for(T::const_iterator it=x.begin(); it!=x.end(); ++it,++i) if( *it == v ) return i; PyErr_SetString(PyExc_ValueError, "Value not in the list"); throw boost::python::error_already_set(); } static void del(T& x, int i) { if( i<0 ) i += x.size(); iter_type it = x.begin(); for (int pos = 0; pos < i; ++pos) ++it; if( i >= 0 && i < (int)x.size() ) { x.erase(it); } else { PyErr_SetString(PyExc_IndexError, "Index out of range"); boost::python::throw_error_already_set(); } } static value_type& get(T& x, int i) { if( i < 0 ) i += x.size(); if( i >= 0 && i < (int)x.size() ) { iter_type it = x.begin(); for(int pos = 0; pos < i; ++pos) ++it; return *it; } else { PyErr_SetString(PyExc_IndexError, "Index out of range"); throw boost::python::error_already_set(); } } static void set(T& x, int i, value_type const& v) { if( i < 0 ) i += x.size(); if( i >= 0 && i < (int)x.size() ) { iter_type it = x.begin(); for(int pos = 0; pos < i; ++pos) ++it; *it = v; } else { PyErr_SetString(PyExc_IndexError, "Index out of range"); boost::python::throw_error_already_set(); } } }; template<class T> void export_STLList(const char* typeName) { using namespace boost::python; class_<std::list<T> >(typeName) .def("__len__", &std::list<T>::size) .def("clear", &std::list<T>::clear) .def("append", &listwrap<T>::add, with_custodian_and_ward<1,2>()) // to let container keep value .def("__getitem__", &listwrap<T>::get, return_value_policy<copy_non_const_reference>()) .def("__setitem__", &listwrap<T>::set, with_custodian_and_ward<1,2>()) // to let container keep value .def("__delitem__", &listwrap<T>::del) .def("__contains__", &listwrap<T>::in) .def("__iter__", iterator<std::list<T> >()) .def("index", &listwrap<T>::index); } 

Применение:

 typedef std::list<int> intlist; export_STLList<int>("intlist"); 

Если достаточно односторонней (от c ++ до python) обертки, вы можете определить прямой конвертер из list<list<YourClass> > – см. Мой векторный векторный вектор <string>> – просто измените типы по мере необходимости, и не забудьте зарегистрировать конвертер .

У вас также может быть метод, возвращающий python::list (который сам будет содержать python::list с вашими объектами), который будет перебирать вложенный список c ++ и строить из него собственный список python, но он будет работать только в одном случае у тебя есть.

Для двухсторонних преобразований либо посмотрите на мой файл (который содержит конвертеры двух сторон для разных типов) – преимущество в том, что вы получаете собственные списки python, недостаток копирует объекты. Для двусторонней конверсии больших коллекций, indexing_suite , безусловно, путь.

Существует indexing_suite_v2 , который, как утверждается, намного лучше, включая прямую поддержку std::list и std::map , хотя, к сожалению, довольно плохо документирован (в прошлый раз я смотрел около 1,5 лет назад) и не являлся официальной частью boost::python .

Python - лучший язык программирования в мире.