Wickeln einer Liste von structs mit boost.python

Ich habe eine C ++ – Funktion, die eine Liste von structs zurückgibt. Innerhalb der Struktur gibt es mehr Listen von Strukturen.

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

Dann für den Export es war ich mit:

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

Und es war OK, seit ich Cout benutzte, um die Daten auf dem Bildschirm zu drucken … Ich möchte jetzt den Rückgabewert verwenden und es ist der Inhalt von pythonähnlichen Eigenschaften, auf diese Weise:

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

Ist das überhaupt möglich ?? Soll ich stattdessen add_property verwenden? Ich glaube nicht, dass ich für jede Struktur eine Klasse erstellen kann. Dieser Entwurf machte Sinn, während ich an C ++ arbeitete, aber jetzt, wo ich ihn einpacken musste, werde ich immer mehr verwirrt.

Jeder Rat zum Wrapping std :: list mit boost.python auf eine allgemeine Weise wäre sehr gut akzeptiert.

Bearbeiten:

Ich werde hier Links hinzufügen, die ich als nützlich gefunden habe: Iteratoren StlContainers

    2 Solutions collect form web for “Wickeln einer Liste von structs mit boost.python”

    Muss es std::list ? Wenn du stattdessen std::vector kannst du boost::python::vector_indexing_suite , um die Liste zu verpacken. Siehe diesen Beitrag für Details.

    Wenn du die std::list musst, musst du eine Helper-Klasse erstellen, die die std::list Funktionalität mit Python- list umschließt. Das kann sehr beteiligt sein, aber machbar.

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

    Verwendung:

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

    Wenn man einen Weg (von c ++ zu python) einpacken kann, dann können Sie einen direkten Konverter aus der list<list<YourClass> > – sehen Sie meinen Vektor <vector <string list<list<YourClass> > Konverter – ändern Sie einfach Typen, wie Sie benötigen, Und vergessen Sie nicht, den Konverter zu registrieren .

    Du könntest auch eine Methode, die python::list (die selbst python::list 's mit deinen Objekten enthält), die über c ++ verschachtelte Liste iterieren und native Python-Liste aus ihr heraus bauen würde, aber es würde nur in einem Fall funktionieren du hast.

    Für Zwei-Wege-Conversions, werfen Sie einen Blick auf meine Datei (die Beide-Wege-Konverter für verschiedene Typen enthält) – Vorteil, erhalten Sie native Python-Listen, Disadvatage ist das Kopieren der Objekte. Für die Zwei-Wege-Umwandlung von großen Sammlungen ist indexing_suite definitiv der Weg zu gehen.

    Es gibt indexing_suite_v2 , was angeblich viel besser ist, einschließlich direkter Unterstützung für std::list und std::map , obwohl leider ziemlich schlecht dokumentiert (letztes mal sah ich vor etwa 1,5 jahren) und nicht offizieller teil von boost::python .

    Python ist die beste Programmiersprache der Welt.