如何将std::map作为参数传递给Python?C++调用问题排查
问题描述
现有如下C++代码:
const std::string Get(const std::map<std::string, std::string> map) { PyObject* module = PyImport_ImportModule("dummy"); boost::python::dict dict; for (auto const& pair : map) { dict[pair.first] = pair.second; } // 出错的行 PyObject* args = PyTuple_Pack(1, &dict); /// ^^^^^^^^^^^ PyObject* function = PyObject_GetAttrString(module,"get_something"); PyObject* pyResult = PyObject_CallObject(function, args); std::string result = PyUnicode_AsUTF8(pyResult); return result; }
对应的Python脚本:
def get_something(map): return map['a']
遇到的问题:可以通过PyUnicode_FromString传递std::string到Python,但找不到直接接收std::map返回PyObject*的函数;尝试传递boost::python::dict引用、直接传map本身都出现段错误;不想用JSON编码或包装类,求简洁最优解。
修复方案
段错误的核心原因是你在PyTuple_Pack中传递了&dict(boost::python::dict对象的地址),但PyTuple_Pack需要的是PyObject指针,而boost::python::dict可以隐式转换为PyObject*,不需要取地址。
基础修复(保留手动PyObject操作)
修改关键行代码即可:
// 正确写法:直接传dict的PyObject指针,而非对象地址 PyObject* args = PyTuple_Pack(1, dict.ptr()); // 也可以直接写dict,Boost.Python会自动隐式转换为PyObject* // PyObject* args = PyTuple_Pack(1, dict);
更简洁的Boost.Python原生写法
直接利用Boost.Python的封装接口,避免手动管理PyObject,代码更简洁且不易出错:
const std::string Get(const std::map<std::string, std::string>& map) { // 用Boost.Python的object封装模块和函数 boost::python::object module = boost::python::import("dummy"); boost::python::object get_something = module.attr("get_something"); boost::python::dict dict; for (const auto& pair : map) { dict[pair.first] = pair.second; } // 直接调用Python函数,自动处理参数和返回值转换 std::string result = boost::python::extract<std::string>(get_something(dict)); return result; }
额外优化建议
- 将函数参数
const std::map<std::string, std::string> map改为const std::map<std::string, std::string>& map,避免不必要的拷贝 - 若坚持手动操作PyObject,记得调用
Py_DECREF释放args、function、pyResult等对象,避免内存泄漏;Boost.Python会自动管理对象生命周期,无需手动释放
内容的提问来源于stack exchange,提问作者Roy Falk
相关产品推荐
相关产品推荐

