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

如何在C++中加载可执行文件目录下的Python模块?

问题描述

我的安装目录结构如下:

install_folder\
- app.exe
- lib.dll
- python\
  - kitsu.py

我尝试在C应用程序中调用kitsu.py文件中的部分函数,C代码(main.cpp)如下:

TCHAR curr_path[MAX_PATH]; 
DWORD length = GetModuleFileName(nullptr, curr_path, MAX_PATH);
PathRemoveFileSpec(curr_path, MAX_PATH);
PyObject* pName, * pModule, * pDict, * pFunc, * pValue, * presult, * sys, * python_folder, * fromlist, * syspathres;

// Initialize the Python Interpreter
Py_Initialize();

// Build the name object
pName = PyUnicode_FromString((char*)"kitsu");
python_folder = PyUnicode_FromString((char*)".python");

PyObject* py_curr_path = PyUnicode_FromString((char*)curr_path);
char command[MAX_PATH];
sprintf(command, "sys.path.append(%s)", curr_path);

PyRun_SimpleString("import sys");
PyRun_SimpleString(command);

fromlist = PyTuple_Pack(1, python_folder);

// Load the module object
pModule = PyImport_ImportModuleEx((char*)"kitsu", nullptr, nullptr, fromlist);
PyObject* init_kitsu = PyObject_GetAttrString(pModule, (char*)"init_kitsu");

presult = PyObject_CallObject(init_kitsu, nullptr); 

(注:这是早期阶段代码,可能存在格式不规范问题)

应用程序运行时崩溃,原因是pModule为空指针,请问为何无法加载该模块?


问题分析与解决

核心原因

导致模块加载失败的关键问题有三个:

  1. 路径语句格式错误:sprintf生成的sys.path.append(%s)没有给路径加引号,Python会把路径当作变量而非字符串,执行直接报错。
  2. 未添加目标子目录到Python路径:kitsu.py在install_folder\python下,但你只把install_folder加入了sys.path,Python找不到存放模块的子目录。
  3. fromlist参数滥用:PyImport_ImportModuleEx的fromlist参数用于指定要导入的子模块,你传入.python完全不符合该参数的使用逻辑,反而干扰了模块查找流程。

修复步骤

  1. 修正路径添加逻辑:
    要么给路径字符串加上引号,确保Python能识别:
    sprintf(command, "sys.path.append(r'%s')", curr_path);
    
    要么用Python C API的方式添加路径,避免字符串拼接的隐患:
    PyRun_SimpleString("import sys");
    sys = PyImport_ImportModule("sys");
    PyObject* path = PyObject_GetAttrString(sys, "path");
    // 添加主目录
    PyList_Append(path, py_curr_path);
    // 添加python子目录
    PyObject* python_path = PyUnicode_FromFormat("%S\\python", py_curr_path);
    PyList_Append(path, python_path);
    // 释放资源
    Py_DECREF(python_path);
    Py_DECREF(path);
    Py_DECREF(sys);
    
  2. 简化模块导入:直接使用PyImport_ImportModule导入kitsu即可,不需要错误使用PyImport_ImportModuleEx:
    pModule = PyImport_ImportModule("kitsu");
    
  3. 添加错误检查:每次调用Python API后检查返回值,避免空指针崩溃:
    if (pModule == nullptr) {
        PyErr_Print(); // 打印Python原生错误信息,快速定位问题
        return -1;
    }
    PyObject* init_kitsu = PyObject_GetAttrString(pModule, "init_kitsu");
    if (init_kitsu == nullptr || !PyCallable_Check(init_kitsu)) {
        PyErr_Print();
        Py_DECREF(pModule);
        return -1;
    }
    

额外注意事项

  • 确保编译程序使用的Python版本和运行时的Python版本完全一致,否则会出现兼容性崩溃。
  • TCHAR是宽字符类型,直接强转char*会导致路径乱码,建议用PyUnicode_FromWideChar处理宽字符串:
    PyObject* py_curr_path = PyUnicode_FromWideChar(curr_path, wcslen(curr_path));
    

内容的提问来源于stack exchange,提问作者hi everybody

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 12:12:28