I use Boost.Python to open a third-party C ++ API.
The header file I came to declares an iterable class (has begin and end methods) and a custom iterator class with which to iterate: -
// File: data.hpp #include <utility> // for std::pair #include <cstring> // for size_t namespace notmylib { // forward declaration class DataIterator; // Storage for arbitrary data class Data { public: Data(void); virtual ~Data(void); // ... typedef DataIterator const_iterator; const_iterator begin(void) const; const_iterator end(void) const; typedef std::pair<int, int> TRange; private: TRange m_data; }; // Data iterator class class DataIterator { public: // constructors DataIterator(void); DataIterator(const Data); ~DataIterator(void); // copy constructor DataIterator(const DataIterator& iter); // assignment operator DataIterator& operator=(const DataIterator& iter); // Comparison operators bool operator==(const DataIterator& iter) const; bool operator!=(const DataIterator& iter) const; // Data Range typedef TData::TRange TRange; TRange GetRange(void) const; Data GetRangeAsData(void) const; // Go backwards one step void Rewind(void); private: Data m_data; size_t m_index; }; }
I created minimal wrapper classes, getting from them: -
// File: pydata.hpp
And Boost.Python declaration: -
// File: pydata.cpp #include "pydata.hpp" #include <boost/python/class.hpp> #include <boost/python/iterator.hpp> #include <boost/python/module.hpp> BOOST_PYTHON_MODULE(const_iterator) { using namespace boost::python; class_<mylib::PyData, boost::noncopyable>("Data", "Iterable Data storage class.") .def("__iter__", iterator<const mylib::PyData>() /*, // */ ) ///< iterator / range / iterators ? // boost::python::return_value_policy< ///< This CallPolicy // boost::python::copy_const_reference> >() ) /// doesn't work either ; class_<mylib::PyIterator>("DataIterator", "Iterator for Data class. Don't actually need to expose...") .def("__eq__", &mylib::PyIterator::operator==) .def("__neq__", &mylib::PyIterator::operator!=) // ... ; }
The only oddity here seems to be to use a const_iterator typedef. This is described in the documentation of the Boost.Python iterator , and from what I am collecting, all it needs is the const qualifier in the iterator template parameters. i.e.
boost::python::iterator<const mylib::PyData>()
However, this leads to the following compiler error using GCC 4.7.2 on Linux x86_64: -
g++ -std=gnu++98 -c -g -O1 -fPIC -I/usr/include/python2.7 pydata.cpp -o pydata.o
In file included from /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_algobase.h:66:0, from /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/memory:64, from /usr/include/boost/config/no_tr1/memory.hpp:21, from /usr/include/boost/get_pointer.hpp:14, from /usr/include/boost/python/object/pointer_holder.hpp:11, from /usr/include/boost/python/to_python_indirect.hpp:10, from /usr/include/boost/python/converter/arg_to_python.hpp:10, from /usr/include/boost/python/call.hpp:15, from /usr/include/boost/python/object_core.hpp:14, from /usr/include/boost/python/object/class.hpp:9, from /usr/include/boost/python/class.hpp:13, from pydata.cpp:4: /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_iterator_base_types.h: In instantiation of 'struct std::iterator_traits<notmylib::DataIterator>': /usr/include/boost/detail/iterator.hpp:81:8: required from 'struct boost::detail::iterator_traits<notmylib::DataIterator>' /usr/include/boost/python/object/iterator.hpp:58:17: required from 'struct boost::python::objects::iterator_range<boost::python::return_value_policy<boost::python::return_by_value>, notmylib::DataIterator>::next' /usr/include/boost/python/object/iterator.hpp:127:45: required from 'boost::python::api::object boost::python::objects::detail::demand_iterator_class(const char*, Iterator*, const NextPolicies&) [with Iterator = notmylib::DataIterator; NextPolicies = boost::python::return_value_policy<boost::python::return_by_value>]' /usr/include/boost/python/object/iterator.hpp:167:11: required from 'boost::python::objects::iterator_range<NextPolicies, Iterator> boost::python::objects::detail::py_iter_<Target, Iterator, Accessor1, Accessor2, NextPolicies>::operator()(boost::python::back_reference<Target&>) const [with Target = const mylib::PyData; Iterator = notmylib::DataIterator; Accessor1 = boost::_bi::protected_bind_t<boost::_bi::bind_t<notmylib::DataIterator, notmylib::DataIterator (*)(const mylib::PyData&), boost::_bi::list1<boost::arg<1> > > >; Accessor2 = boost::_bi::protected_bind_t<boost::_bi::bind_t<notmylib::DataIterator, notmylib::DataIterator (*)(const mylib::PyData&), boost::_bi::list1<boost::arg<1> > > >; NextPolicies = boost::python::return_value_policy<boost::python::return_by_value>]' /usr/include/boost/python/detail/invoke.hpp:75:82: required from 'PyObject* boost::python::detail::invoke(boost::python::detail::invoke_tag_<false, false>, const RC&, F&, AC0&) [with RC = boost::python::to_python_value<const boost::python::objects::iterator_range<boost::python::return_value_policy<boost::python::return_by_value>, notmylib::DataIterator>&>; F = boost::python::objects::detail::py_iter_<const mylib::PyData, notmylib::DataIterator, boost::_bi::protected_bind_t<boost::_bi::bind_t<notmylib::DataIterator, notmylib::DataIterator (*)(const mylib::PyData&), boost::_bi::list1<boost::arg<1> > > >, boost::_bi::protected_bind_t<boost::_bi::bind_t<notmylib::DataIterator, notmylib::DataIterator (*)(const mylib::PyData&), boost::_bi::list1<boost::arg<1> > > >, boost::python::return_value_policy<boost::python::return_by_value> >; AC0 = boost::python::arg_from_python<boost::python::back_reference<const mylib::PyData&> >; PyObject = _object]' /usr/include/boost/python/detail/caller.hpp:223:13: required from 'PyObject* boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = boost::python::objects::detail::py_iter_<const mylib::PyData, notmylib::DataIterator, boost::_bi::protected_bind_t<boost::_bi::bind_t<notmylib::DataIterator, notmylib::DataIterator (*)(const mylib::PyData&), boost::_bi::list1<boost::arg<1> > > >, boost::_bi::protected_bind_t<boost::_bi::bind_t<notmylib::DataIterator, notmylib::DataIterator (*)(const mylib::PyData&), boost::_bi::list1<boost::arg<1> > > >, boost::python::return_value_policy<boost::python::return_by_value> >; Policies = boost::python::default_call_policies; Sig = boost::mpl::vector2<boost::python::objects::iterator_range<boost::python::return_value_policy<boost::python::return_by_value>, notmylib::DataIterator>, boost::python::back_reference<const mylib::PyData&> >; PyObject = _object]' /usr/include/boost/python/object/py_function.hpp:38:33: required from 'PyObject* boost::python::objects::caller_py_function_impl<Caller>::operator()(PyObject*, PyObject*) [with Caller = boost::python::detail::caller<boost::python::objects::detail::py_iter_<const mylib::PyData, notmylib::DataIterator, boost::_bi::protected_bind_t<boost::_bi::bind_t<notmylib::DataIterator, notmylib::DataIterator (*)(const mylib::PyData&), boost::_bi::list1<boost::arg<1> > > >, boost::_bi::protected_bind_t<boost::_bi::bind_t<notmylib::DataIterator, notmylib::DataIterator (*)(const mylib::PyData&), boost::_bi::list1<boost::arg<1> > > >, boost::python::return_value_policy<boost::python::return_by_value> >, boost::python::default_call_policies, boost::mpl::vector2<boost::python::objects::iterator_range<boost::python::return_value_policy<boost::python::return_by_value>, notmylib::DataIterator>, boost::python::back_reference<const mylib::PyData&> > >; PyObject = _object]' pydata.cpp:26:1: required from here /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_iterator_base_types.h:166:53: error: no type named 'iterator_category' in 'class notmylib::DataIterator' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_iterator_base_types.h:167:53: error: no type named 'value_type' in 'class notmylib::DataIterator' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_iterator_base_types.h:168:53: error: no type named 'difference_type' in 'class notmylib::DataIterator' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_iterator_base_types.h:169:53: error: no type named 'pointer' in 'class notmylib::DataIterator' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_iterator_base_types.h:170:53: error: no type named 'reference' in 'class notmylib::DataIterator'
How should such an iterative class be displayed?
Cheers, Alex