在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
相关产品推荐
相关产品推荐

