使用Python C API在C++中解析Python返回字符串遇段错误求助
Python C API调用字符串返回值时出现段错误的解决思路
我在C++代码中使用Python C API调用Python编写的函数,目前能够解析Python返回的列表、字典,但在解析返回的字符串时出现了段错误。附上相关代码,恳请大家提供解决思路。
Python代码(hell.py)
import json ### 示例代码,需要返回该字符串 def get_json(): res = '{"Hello": [2.3, 4.5, 7.8], "How": 0, "Why": "no"}' # 要返回的示例字典 a = json.loads(res) print(a) l1 = json.dumps(a) # 转为字符串 return l1 # 返回该字符串
原C++代码(存在问题)
#define PY_SSIZE_T_CLEAN #include</usr/include/python3.6/Python.h> #include <bits/stdc++.h> PyObject *mymodule = PyImport_ImportModule("hell"); PyErr_Print(); PyObject *myfunc = PyObject_GetAttrString(mymodule, "get_json"); PyErr_Print(); PyObject *result1 = PyObject_CallObject(myfunc1, NULL); PyErr_Print(); char * buff = new char[100]; buff = PyByteArray_AsString(result1); cout<<buff[0]<<endl; // 此处出现段错误
问题分析与修正方案
1. 变量名错误
原代码调用PyObject_CallObject时用了未定义的myfunc1,实际函数指针是myfunc,野指针调用直接触发内存错误。
2. 类型不匹配导致非法访问
PyByteArray_AsString仅适用于PyByteArray类型对象,但Python返回的是PyUnicode类型字符串(Python3默认字符串类型),用错函数会访问非法内存区域,引发段错误。
3. 内存泄漏
先new char[100]分配内存,随后直接将buff指向其他地址,导致之前的内存无法释放。
修正后的C++代码
#define PY_SSIZE_T_CLEAN #include </usr/include/python3.6/Python.h> #include <iostream> int main() { // 必须初始化Python解释器,原代码遗漏此步骤 Py_Initialize(); if (!Py_IsInitialized()) { std::cerr << "Python初始化失败" << std::endl; return 1; } PyObject *mymodule = PyImport_ImportModule("hell"); if (!mymodule) { PyErr_Print(); Py_Finalize(); return 1; } PyObject *myfunc = PyObject_GetAttrString(mymodule, "get_json"); if (!myfunc || !PyCallable_Check(myfunc)) { PyErr_Print(); Py_DECREF(mymodule); Py_Finalize(); return 1; } // 修正变量名:myfunc1 → myfunc PyObject *result1 = PyObject_CallObject(myfunc, NULL); if (!result1) { PyErr_Print(); Py_DECREF(myfunc); Py_DECREF(mymodule); Py_Finalize(); return 1; } // 处理Python Unicode字符串:转为UTF-8编码的C字符串 PyObject *utf8_bytes = PyUnicode_AsUTF8String(result1); if (!utf8_bytes) { PyErr_Print(); Py_DECREF(result1); Py_DECREF(myfunc); Py_DECREF(mymodule); Py_Finalize(); return 1; } const char *buff = PyBytes_AsString(utf8_bytes); if (buff) { std::cout << buff << std::endl; } // Python3.3+ 也可直接用以下方式,返回内存由Python管理 // const char *buff = PyUnicode_AsUTF8(result1); // if (buff) std::cout << buff << std::endl; // 释放Python对象引用,避免内存泄漏 Py_DECREF(utf8_bytes); Py_DECREF(result1); Py_DECREF(myfunc); Py_DECREF(mymodule); // 关闭Python解释器 Py_Finalize(); return 0; }
额外注意事项
- 必须调用
Py_Initialize()初始化Python解释器,否则会出现未定义行为。 - 所有创建的PyObject都要用
Py_DECREF()释放引用,避免内存泄漏。 - 每一步Python API调用后都要检查返回值是否为NULL,及时处理错误并释放资源。
内容的提问来源于stack exchange,提问作者ABD
相关产品推荐
相关产品推荐

