在C++中嵌入Python:如何解析Python函数返回的列表?
在C++中解析Python返回的嵌套浮点列表
你需要通过递归方式解析Python返回的嵌套列表,因为列表元素可能是子列表或浮点值。以下是完整的代码示例,将Python嵌套列表转换为C++的std::vector<std::vector<double>>:
完整代码实现
首先定义递归解析函数,再在你的调用逻辑中使用:
#include <vector> #include <iostream> #include <Python.h> // 递归解析单层浮点列表(用于嵌套结构中的子列表) bool ParseFloatList(PyObject* pList, std::vector<double>& outVec) { Py_ssize_t size = PyList_Size(pList); for (Py_ssize_t i = 0; i < size; ++i) { PyObject* pItem = PyList_GetItem(pList, i); // 借用引用,无需手动释放 // 处理浮点值 if (PyFloat_Check(pItem)) { outVec.push_back(PyFloat_AsDouble(pItem)); } // 兼容Python整数(自动转为double) else if (PyLong_Check(pItem)) { outVec.push_back(static_cast<double>(PyLong_AsLongLong(pItem))); } // 遇到非预期类型,抛出错误 else { PyErr_SetString(PyExc_TypeError, "List contains non-numeric value"); return false; } } return true; } // 解析嵌套列表(外层列表的元素是子列表) bool ParseNestedFloatList(PyObject* pNestedList, std::vector<std::vector<double>>& outNestedVec) { if (!PyList_Check(pNestedList)) { PyErr_SetString(PyExc_TypeError, "Expected nested list as return value"); return false; } Py_ssize_t outerSize = PyList_Size(pNestedList); for (Py_ssize_t i = 0; i < outerSize; ++i) { PyObject* pSubList = PyList_GetItem(pNestedList, i); if (!PyList_Check(pSubList)) { PyErr_SetString(PyExc_TypeError, "Nested structure contains non-list element"); return false; } std::vector<double> subVec; if (!ParseFloatList(pSubList, subVec)) { return false; } outNestedVec.push_back(subVec); } return true; } // 你的原有调用逻辑 int main() { // 初始化Python环境(必须添加) Py_Initialize(); PyObject *pFunction, *pArguments, *pArgumentValue; // 假设你已经通过PyImport_ImportModule、PyObject_GetAttrString等获取了pFunction和pArguments pArgumentValue = PyObject_CallObject(pFunction, pArguments); Py_DECREF(pArguments); if (pArgumentValue != NULL) { // 解析嵌套列表 std::vector<std::vector<double>> parsedData; if (ParseNestedFloatList(pArgumentValue, parsedData)) { // 解析成功,示例遍历输出数据 std::cout << "Parsed nested list:\n"; for (const auto& subList : parsedData) { for (double val : subList) { std::cout << val << " "; } std::cout << "\n"; } } else { PyErr_Print(); } // 释放返回值的引用 Py_DECREF(pArgumentValue); } else { PyErr_Print(); } // 关闭Python环境 Py_Finalize(); return 0; }
关键注意事项
- 引用计数:
PyList_GetItem返回的是借用的引用,无需手动调用Py_DECREF;但PyObject_CallObject返回的pArgumentValue是新引用,必须调用Py_DECREF释放。 - 类型检查:必须先判断对象类型(
PyList_Check、PyFloat_Check等),避免非法内存访问。 - 错误处理:解析失败时通过
PyErr_SetString设置Python错误,再用PyErr_Print输出错误信息。 - 兼容性:代码兼容Python返回的整数类型,自动转为
double,如果不需要可以去掉这部分判断。
内容的提问来源于stack exchange,提问作者robotanical
相关产品推荐
相关产品推荐

