如何为python iterables编写c ++包装器?

时间:2013-08-02 22:04:51

标签: c++ boost-python

我有一个C ++函数,它需要一个vector< pair< pair<string,string>, string > >,我希望从python中调用它。

我写了一个包装如下:

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);
}

我已经用python注册了这个函数,如下所示:

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

这很好但问题是,它只接受元组但不接受列表。我如何编写包装器,以便它在python中的任何序列容器中工作?有没有更好的方法来做到这一点,而无需编写包装器?我希望python api像

一样简单
create_cache( ( (('',''),'b1'), ) )
create_cache( [ (('',''),'b1')  ] )

2 个答案:

答案 0 :(得分:2)

这可以通过使包装器取代对象来实现:

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

py::len()并且索引操作符应该处理对象,如果有问题的类型不支持len()或索引,它们应该引发Python错误。这应该允许调用者提供任何可索引类型,甚至是用户定义的类型!

答案 1 :(得分:1)

我通常使用boost python iterator wrappers来实现您所描述的内容 - 它适用于任何类型的可迭代。我在下面修改了你的代码,这样你就可以自己了解如何做到这一点:

#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);
}

您可以使用stl_input_iterator一直使用,即使是第一个可迭代内的对子也可以。