troy 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


Thank you very much for the email, you did put me on the right track and 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@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to