如何声明可接受任意Python可迭代对象的C++函数?
解决方案
1. 接受任意Python可迭代对象
直接把函数参数类型改成boost::python::object,借助Boost.Python的迭代器适配Python的迭代协议,所有实现了__iter__方法的对象(包括列表、元组、集合、生成器、自定义迭代类等)都能正常传入。
示例代码:
#include <boost/python.hpp> #include <boost/python/iterator.hpp> using namespace boost::python; void myf(const object& iterable) { // 创建迭代器遍历可迭代对象 iterator iter_begin(iterable), iter_end; for (; iter_begin != iter_end; ++iter_begin) { object elem = *iter_begin; // 根据需求处理元素,比如转为C++类型 if (extract<int>(elem).check()) { int value = extract<int>(elem); // 这里写入你的业务逻辑,比如处理value } else { // 类型不匹配时抛出Python异常 PyErr_SetString(PyExc_TypeError, "元素类型不符合要求"); throw_error_already_set(); } } } BOOST_PYTHON_MODULE(your_module) { def("myf", &myf); }
2. 退而求其次接受任意集合(序列/集合类型)
如果只需要支持list、tuple、set这类集合类型,可以在函数内部先做类型检查。不过第一种方案已经覆盖了这些集合类型,更推荐直接用第一种。要是要严格限制为集合,可结合PySequence_Check或PySet_Check判断:
示例代码:
void myf(const object& collection) { // 检查是否是序列(list、tuple等)或集合 if (!PySequence_Check(collection.ptr()) && !PySet_Check(collection.ptr())) { PyErr_SetString(PyExc_TypeError, "必须传入序列或集合类型"); throw_error_already_set(); } // 后续遍历逻辑同可迭代对象方案 iterator iter_begin(collection), iter_end; for (; iter_begin != iter_end; ++iter_begin) { object elem = *iter_begin; // 处理元素... } }
关键说明
- 用
boost::python::object做参数是最灵活的方式,能兼容所有Python对象,再通过迭代器或类型检查筛选目标对象。 - 转换Python对象到C++类型时,用
extract<T>的check()方法判断转换是否成功,避免运行时出错。
内容的提问来源于stack exchange,提问作者MMM
相关产品推荐
相关产品推荐

