c++ - wrapping a list of structs with boost.python -
i have c++ function returns list of structs. inside struct, there more lists of structs.
struct camerainfo { camname name; std::list<camimageformat> limgformats; std::list<camcontrols> lcamcontrols; }; std::list<camerainfo> getcamerainfo() { std::list<camerainfo> lcamerasinfo; // fill lcamerasinfo return lcamerasinfo; }
then exporting using:
class_<cameranode....> >("cameranode", no_init) ... ... .def("listcamerainfo", make_function(&cameranode::listcamerainfo)) .staticmethod("listcamerainfo") ... ;
and ok since using cout print data on screen... use return value , it's content python properties, way:
cameras = [] cameras = cameranode.getcamerainfo() print cameras[0].name print cameras[0].limgformats[0] , on...
is possible?? should using add_property instead? don't think can create class every struct. design made sense while working on c++ have wrap it, i'm getting more , more confused.
any advice on wrapping std::list boost.python in general way accepted.
edit:
i add here links i've found useful: iterators stlcontainers
does have std::list
? if use std::vector
instead can use boost::python::vector_indexing_suite
wrap list. see this post details.
if must use std::list
you'll need create helper class wraps std::list
functionality python's list
methods. can quite involved, doable.
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 = 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 list"); throw boost::python::error_already_set(); } static void del(t& x, int i) { if( i<0 ) += x.size(); iter_type = x.begin(); (int pos = 0; pos < i; ++pos) ++it; if( >= 0 && < (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( < 0 ) += x.size(); if( >= 0 && < (int)x.size() ) { iter_type = 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( < 0 ) += x.size(); if( >= 0 && < (int)x.size() ) { iter_type = 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>()) // 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>()) // 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); }
usage:
typedef std::list<int> intlist; export_stllist<int>("intlist");
Comments
Post a Comment