You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:05:18