如何为python可迭代内容编写c++包装器

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

本文关键字:c++ 包装 python 迭代      更新时间:2023-10-16

我有一个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')  ] )

这可以通过让包装器接受一个对象来实现:

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

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

我通常使用boost-python迭代器包装来实现您所描述的内容——它可以与任何类型的可迭代程序一起使用。我在下面修改了你的代码,这样你就有了自己的想法:

#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,即使对于第一个可迭代项中的对也是如此。