balki
balki

Reputation: 27684

How to write a c++ wrapper for python iterables?

I have a C++ function which takes a vector< pair< pair<string,string>, string > > which I wish to call from python.

I wrote a wrapper as below:

bool create_cache_wrapper(boost::python::tuple tup_)
{
  vector< pair< pair<string,string>, string > > rbv;
  for(int i=0;i<py::len(tup_);++i)
  {
    std::string start,end,bucket;
    bucket = py::extract<std::string>(tup_[i][1]);
    start = py::extract<std::string>(tup_[i][0][0]);
    end = py::extract<std::string>(tup_[i][0][1]);
    rbv.push_back(make_pair(make_pair(start,end),bucket));
  }
  return create_cache(rbv);
}

I have registered this function with python as below:

BOOST_PYTHON_MODULE(my_lib)
{
  using namespace boost::python;
  def("create_cache", create_cache_wrapper);
}

This works fine but the issue is, it accepts only a tuple but not a list. How do I write the wrapper such that it works any sequence container in python? Is there a better way to do this without having to write a wrapper? I want the python api to be simple like

create_cache( ( (('',''),'b1'), ) )
create_cache( [ (('',''),'b1')  ] )

Upvotes: 3

Views: 382

Answers (2)

Andr&#233; Anjos
Andr&#233; Anjos

Reputation: 5309

I normally use boost python iterator wrappers to achieve what you described - it works with any type of iterable. I adapted your code below so you have an idea on how to do it yourself:

#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>

using namespace boost::python;

bool create_cache_wrapper(object iterable)
{
  stl_input_iterator<object> end;
  for(std_input_iterator<object> i(iterable); i!=end; ++i)
  {
    std::string start,end,bucket;
    bucket = py::extract<std::string>((*i)[1]);
    start = py::extract<std::string>((*i)[0][0]);
    end = py::extract<std::string>((*i)[0][1]);
    rbv.push_back(make_pair(make_pair(start,end),bucket));
  }
  return create_cache(rbv);
}

You can go all the way using stl_input_iterator, even for the your pairs inside the first iterable.

Upvotes: 1

cdhowie
cdhowie

Reputation: 169403

This could be accomplished by making the wrapper take an object instead:

bool create_cache_wrapper(boost::python::object tup_)
{
    // ...
}

py::len() and the indexing operators should work on objects, and they should raise a Python error if the type in question does not support len() or indexing. This should allow the caller to provide any indexable type, even user-defined ones!

Upvotes: 2

Related Questions