|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
Iterators for heterogeneous containerI am having trouble wrapping a container that can hold multiple object
types and therefore has multiple iterator types. My C++ library has these classes: class Tomato; class Potato; class Garden { Iter<Tomato> get_tomatoes(); Iter<Potato> get_potatoes(); }; template<class T> class Iter { T get_next(); }; which allows to write: Iter<Potato> potatoes = garden.get_potatoes(); while (Potato potato = potatoes.get_next()) { cout << potato.name(); } I am trying to use boost to wrap it so that I can write in python: for potato in garden.get_potatoes(): print potato.name() Any pointers how to achieve this with boost? _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@... http://mail.python.org/mailman/listinfo/cplusplus-sig |
|
|
Re: Iterators for heterogeneous containerThomas,
I think the answer is here: http://www.boost.org/doc/libs/1_40_0/libs/python/doc/tutorial/doc/html/python/iterators.html but you should modify your "Garden" class in order to support "begin" and "end" iterators for "tomatoes" and "potatoes". With these modifications: class Garden { public: typedef .... Tomato_Iter; typedef .... Potato_Iter; Tomato_Iter tomatoes_begin(); Tomato_Iter tomatoes_end(); Potato_Iter potatoes_begin(); Potato_Iter potatoes_end(); }; you can expose your Garden class as here: class_<Garden>("Garden") .property("tomatoes", range(&Garden::tomatoes_begin, &Garden::tomatoes_end)) .property("potatoes", range(&Garden::potatoes_begin, &Garden::potatoes_end)); At this point, in Python, you should be able to write: for potato in garden.potatoes: .... and do here whatever you want ... It's the best I can suggest 2009/11/6 Thomas Daniel <thomasd57@...>: > I am having trouble wrapping a container that can hold multiple object types > and therefore has multiple iterator types. > > My C++ library has these classes: > > class Tomato; > class Potato; > class Garden { > Iter<Tomato> get_tomatoes(); > Iter<Potato> get_potatoes(); > }; > > template<class T> > class Iter { > T get_next(); > }; > > which allows to write: > > Iter<Potato> potatoes = garden.get_potatoes(); > while (Potato potato = potatoes.get_next()) { > cout << potato.name(); > } > > I am trying to use boost to wrap it so that I can write in python: > > for potato in garden.get_potatoes(): > print potato.name() > > Any pointers how to achieve this with boost? > > > > > > _______________________________________________ > Cplusplus-sig mailing list > Cplusplus-sig@... > http://mail.python.org/mailman/listinfo/cplusplus-sig > -- Michele De Stefano http://www.linkedin.com/in/micdestefano http://xoomer.virgilio.it/michele_de_stefano http://code.google.com/p/mds-utils _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@... http://mail.python.org/mailman/listinfo/cplusplus-sig |
|
|
Re: Iterators for heterogeneous containerHi Michele,
Thanks for the pointers, but unfortunately I don't think they apply in my case. It seems that boost support for iterators was written *only* with STL-like iterators in mind. You have to have begin() and end() and to be able to dereference the iterator. I can't do it (or I don't know how to do it). In contrast, my iterators are more like python iteration sequence, with only one method: get_next(), which returns the next object in the container *and* advances the iterator at the same time. I can't dereference this iterator, as you would do in STL. In fact, this seems to be so close to the python iteration model, that a simple approach should be doable: BOOST_PYTHON_MODULE(vegetables) { class_<Garden>("Garden") .def("get_potatoes", &Garden::get_potatoes) .def("get_tomatoes", &Garden::get_tomatoes) ; class_<TomatoIter>("TomatoIter") .def("__iter__", &TomatoIter::get_next) ; } That at least compiles - unlike all my previous attempts that generate three pages of template errors - but python complain: TypeError: iter() returned non-iterator of type 'Tomato' so now I am trying to figure out how to tell boost that get_tomatoes returns an iterator ... Thomas Michele De Stefano wrote: > Thomas, > > I think the answer is here: > http://www.boost.org/doc/libs/1_40_0/libs/python/doc/tutorial/doc/html/python/iterators.html > > but you should modify your "Garden" class in order to support "begin" > and "end" iterators for "tomatoes" and "potatoes". > > With these modifications: > > class Garden { > public: > typedef .... Tomato_Iter; > typedef .... Potato_Iter; > > Tomato_Iter tomatoes_begin(); > Tomato_Iter tomatoes_end(); > Potato_Iter potatoes_begin(); > Potato_Iter potatoes_end(); > }; > > you can expose your Garden class as here: > > class_<Garden>("Garden") > .property("tomatoes", range(&Garden::tomatoes_begin, &Garden::tomatoes_end)) > .property("potatoes", range(&Garden::potatoes_begin, > &Garden::potatoes_end)); > > At this point, in Python, you should be able to write: > > for potato in garden.potatoes: > .... and do here whatever you want ... > > It's the best I can suggest > > > 2009/11/6 Thomas Daniel <thomasd57@...>: > >> I am having trouble wrapping a container that can hold multiple object types >> and therefore has multiple iterator types. >> >> My C++ library has these classes: >> >> class Tomato; >> class Potato; >> class Garden { >> Iter<Tomato> get_tomatoes(); >> Iter<Potato> get_potatoes(); >> }; >> >> template<class T> >> class Iter { >> T get_next(); >> }; >> >> which allows to write: >> >> Iter<Potato> potatoes = garden.get_potatoes(); >> while (Potato potato = potatoes.get_next()) { >> cout << potato.name(); >> } >> >> I am trying to use boost to wrap it so that I can write in python: >> >> for potato in garden.get_potatoes(): >> print potato.name() >> >> Any pointers how to achieve this with boost? >> >> >> >> >> >> _______________________________________________ >> Cplusplus-sig mailing list >> Cplusplus-sig@... >> http://mail.python.org/mailman/listinfo/cplusplus-sig >> >> > > > > Cplusplus-sig mailing list Cplusplus-sig@... http://mail.python.org/mailman/listinfo/cplusplus-sig |
|
|
Re: Iterators for heterogeneous containerThomas Daniel wrote:
> > BOOST_PYTHON_MODULE(vegetables) > { > class_<Garden>("Garden") > .def("get_potatoes", &Garden::get_potatoes) > .def("get_tomatoes", &Garden::get_tomatoes) > ; > class_<TomatoIter>("TomatoIter") > .def("__iter__", &TomatoIter::get_next) > ; > } > > That at least compiles - unlike all my previous attempts that generate > three pages of template errors - but python complain: > > TypeError: iter() returned non-iterator of type 'Tomato' > > so now I am trying to figure out how to tell boost that get_tomatoes > returns an iterator ... > Please don't top-post, guys As you know, python iterators have a function next() that returns the next object in the iteree, or throw StopIteration when they're at the end. As you also know, python expects member functions __iter__() to return an iterator. Is the thing returned by TomatoIter::get_next an iterator, ie does it implement the iterator interface? -t _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@... http://mail.python.org/mailman/listinfo/cplusplus-sig |
|
|
Re: Iterators for heterogeneous containertroy d. straszheim wrote: > Thomas Daniel wrote: >> >> BOOST_PYTHON_MODULE(vegetables) >> { >> class_<Garden>("Garden") >> .def("get_potatoes", &Garden::get_potatoes) >> .def("get_tomatoes", &Garden::get_tomatoes) >> ; >> class_<TomatoIter>("TomatoIter") >> .def("__iter__", &TomatoIter::get_next) >> ; >> } >> >> That at least compiles - unlike all my previous attempts that >> generate three pages of template errors - but python complain: >> >> TypeError: iter() returned non-iterator of type 'Tomato' >> >> so now I am trying to figure out how to tell boost that get_tomatoes >> returns an iterator ... >> > > Please don't top-post, guys > > As you know, python iterators have a function next() that returns the > next object in the iteree, or throw StopIteration when they're at the > end. As you also know, python expects member functions __iter__() to > return an iterator. Is the thing returned by TomatoIter::get_next an > iterator, ie does it implement the iterator interface? > > -t > > I finally figured out how to do it, with help from here also: http://wiki.python.org/moin/boost.python/iterator The solution involves creating a wrapper class around get_next(), which throws StopIteration when done and a "pass_through" function to bind to __iter__: inline TomatoIter pass_through(const TomatoIter& iter) { return iter; } Tomato next(TomatoIter& iter) { Tomato tomato = iter.get_next(); if (!tomato) { PyErr_SetString(PyExc_StopIteration, "No more data."); throw_error_already_set(); } return tomato; } Now, I can do this: BOOST_PYTHON_MODULE(Garden) { ...... class_<TomatoIter>("TomatoIter", no_init) .def("next", next) .def("__iter__", pass_through) ; and it works. Thomas _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@... http://mail.python.org/mailman/listinfo/cplusplus-sig |
| Free embeddable forum powered by Nabble | Forum Help |