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

在Windows应用中调用Python函数遇PyObject_GetAttrString异常求助

问题解决:C++嵌入Python时触发0xC0000005访问违规错误

错误根源

你遇到的访问违规,本质是pModule为空指针,导致后续调用PyObject_GetAttrString时试图访问空指针的内存地址(0x0000000000000008)。pModule为空的核心原因是Python模块导入失败,加上代码缺少错误检查,直接跳过了导入失败的判断逻辑。


具体修复步骤

1. 修正模块名称:去掉.py后缀

PyImport_Import要求传入模块名(不带.py后缀),而非完整文件名。原代码中PyUnicode_FromString((char*)"Downloader.py")是错误的,需改为:

pName = PyUnicode_FromString("Downloader");

2. 强制添加错误检查,定位问题

在每一步Python API调用后检查返回值,一旦失败立即打印错误信息并终止流程,避免空指针后续调用:

  • 检查pName是否创建成功
  • 检查pModule是否导入成功,失败时用PyErr_Print()打印具体错误(比如模块不在Python搜索路径中)
  • 检查pFunc是否存在且可调用

3. 确保Python能找到你的模块

将Downloader.py所在目录添加到Python的sys.path中,有两种方式:

  • 代码内添加(推荐):
    PyObject* sysPath = PySys_GetObject("path");
    // 替换为Downloader.py实际所在的目录
    PyList_Append(sysPath, PyUnicode_FromString("C:\\Users\\User\\Desktop"));
    
  • 环境变量设置:运行C++程序前,设置PYTHONPATH环境变量指向模块目录。

4. 移除不必要的强制类型转换

PyUnicode_FromString的参数是const char*,无需强制转换(char*),直接传字符串字面量即可,避免潜在类型问题。


修正后的完整代码示例

if (SendMessage(download, BM_GETSTATE, 0, 0)) {
    Py_Initialize();

    // 添加模块所在目录到Python搜索路径
    PyObject* sysPath = PySys_GetObject("path");
    PyList_Append(sysPath, PyUnicode_FromString("C:\\Users\\User\\Desktop"));

    PyObject* output = PyUnicode_FromString("C:\\Users\\User\\Desktop");
    PyObject* ytlink = PyUnicode_FromString("https://www.youtube.com/watch?v=G9cyeZfLeQc&ab_channel=FIRSTRoboticsCompetition");
    PyObject* pName, * pModule, * pFunc, * pArgs, * pValue;

    // 模块名去掉.py后缀
    pName = PyUnicode_FromString("Downloader");
    if (!pName) {
        PyErr_Print();
        Py_Finalize();
        return;
    }

    pModule = PyImport_Import(pName);
    Py_DECREF(pName); // 释放不再使用的引用
    if (!pModule) {
        PyErr_Print();
        Py_Finalize();
        return;
    }

    pFunc = PyObject_GetAttrString(pModule, "download");
    if (!pFunc || !PyCallable_Check(pFunc)) {
        PyErr_Print();
        Py_DECREF(pModule);
        Py_Finalize();
        return;
    }

    pArgs = PyTuple_Pack(2, ytlink, output);
    if (!pArgs) {
        PyErr_Print();
        Py_DECREF(pFunc);
        Py_DECREF(pModule);
        Py_Finalize();
        return;
    }

    pValue = PyObject_CallObject(pFunc, pArgs);
    if (!pValue) {
        PyErr_Print();
    } else {
        Py_DECREF(pValue); // 处理返回值后释放引用
    }

    // 释放所有Python对象引用,避免内存泄漏
    Py_DECREF(pArgs);
    Py_DECREF(pFunc);
    Py_DECREF(pModule);
    Py_DECREF(ytlink);
    Py_DECREF(output);

    Py_Finalize();
}

额外注意事项

  • 确保C++项目配置正确:链接对应版本的Python库(Debug模式用python310_d.lib,Release模式用python310.lib),并包含Python头文件目录。
  • 调用Python API后必须用Py_DECREF释放对象引用,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Elliot Scher

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 15:40:28