C++调用Python函数时Py_BuildValue报UnicodeDecodeError问题解决
解决C++调用Python时Py_BuildValue的UnicodeDecodeError问题
问题原因
你遇到的UnicodeDecodeError是因为文件路径的编码并非UTF-8(比如Windows系统下常见的GBK/GB2312编码),而Py_BuildValue("s")默认按UTF-8解析字符串,导致非UTF-8字节解码失败。同时原代码存在一个隐性错误:PyObject_CallObject要求第二个参数是参数元组(即使只有一个参数),直接传递单个字符串对象不符合API要求。
解决方案
以下两种方案可解决编码问题,同时修正参数传递的错误:
方案1:使用宽字符串API(推荐,多系统适配)
直接传递宽字符路径给Python,利用Python的宽字符串处理能力避免编码转换问题:
#include <filesystem> #include <iostream> #include <Python.h> namespace fs = std::filesystem; int main() { PyObject *pName, *pModule, *pFunc, *pValue, *pArg; Py_Initialize(); pName = PyUnicode_FromString("my_module"); pModule = PyImport_Import(pName); pFunc = PyObject_GetAttrString(pModule, "my_func"); std::wstring path = L"my_dir_path"; for (const auto & entry : fs::directory_iterator(path)) { // 用(u)创建包含宽字符串的参数元组 pArg = Py_BuildValue("(u)", entry.path().wstring().c_str()); pValue = PyObject_CallObject(pFunc, pArg); double result = PyFloat_AsDouble(pValue); std::cout << result << std::endl; // 释放临时对象,避免内存泄漏 Py_DECREF(pArg); Py_DECREF(pValue); } // 清理全局对象 Py_DECREF(pFunc); Py_DECREF(pModule); Py_DECREF(pName); Py_Finalize(); return 0; }
方案2:手动转换为UTF-8字符串
将本地编码的路径显式转为UTF-8后再传递:
#include <filesystem> #include <iostream> #include <Python.h> #include <codecvt> #include <locale> namespace fs = std::filesystem; // 辅助函数:宽字符串转UTF-8字符串 std::string wstring_to_utf8(const std::wstring& wstr) { std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; return converter.to_bytes(wstr); } int main() { PyObject *pName, *pModule, *pFunc, *pValue, *pArg; Py_Initialize(); pName = PyUnicode_FromString("my_module"); pModule = PyImport_Import(pName); pFunc = PyObject_GetAttrString(pModule, "my_func"); std::string path = "my_dir_path"; for (const auto & entry : fs::directory_iterator(path)) { std::string utf8_path = wstring_to_utf8(entry.path().wstring()); // 用(s)创建包含UTF-8字符串的参数元组 pArg = Py_BuildValue("(s)", utf8_path.c_str()); pValue = PyObject_CallObject(pFunc, pArg); double result = PyFloat_AsDouble(pValue); std::cout << result << std::endl; Py_DECREF(pArg); Py_DECREF(pValue); } Py_DECREF(pFunc); Py_DECREF(pModule); Py_DECREF(pName); Py_Finalize(); return 0; }
额外注意事项
- 所有Python对象使用完毕后必须调用
Py_DECREF释放,防止内存泄漏; - Windows环境下建议将项目字符集设置为“Unicode字符集”,确保宽字符串处理正常;
- Python侧的
my_func无需修改,Python会自动处理传入的字符串编码。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

