Boost Python exposes some STL iterator wrappers in the "stl_iterator" header that let you go from begin
to end
like a normal C++ iteration:
https://www.boost.org/doc/libs/1_75_0/libs/python/doc/html/reference/high_level_components/boost_python_stl_iterator_hpp.html
For Python version 2 you can use d.items()
or d.iteritems()
depending on whether you want to iterate lazily or not. For Python version 3 has a slight problem - you'd expect items
to be a lazy dict
view, but instead Boost Python converts it to a list. Therefore, I've called .attr("items")()
instead to bypass the in-build conversion thus getting a lazy wrapper. I've returned this object to Python just to confirm that it's the view rather than a list.
Calling stl_input_iterator<tuple>()
gives you an iterator for a (Python) tuple object from which you can extract the key and the value.
#include <boost/python/dict.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/stl_iterator.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/str.hpp>
#include <boost/python.hpp>
#include <iostream>
using namespace boost::python;
object print_dict_to_cout(dict d) {
auto items = d.attr("items")(); // just plain d.items or d.iteritems for Python 2!
for (auto it = stl_input_iterator<tuple>(items); it != stl_input_iterator<tuple>(); ++it) {
tuple kv = *it;
auto key = kv[0];
auto value = kv[1];
std::cout << extract<const char*>(str(key)) << " : " << extract<const char*>(str(value)) << std::endl;
}
return items;
}
BOOST_PYTHON_MODULE(iterdict)
{
def("print_dict_to_cout", print_dict_to_cout);
}
The advantage of doing it this way is that it's lazy, and doesn't create the intermediate list.