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

如何在C++中直接嵌入Python3.11字符串代码并获取返回值?

在C++中嵌入Python 3.11并直接执行字符串源码(获取返回结果)

你可以通过Python C API的PyRun_String配合模块命名空间的方式,直接在内存中执行字符串形式的Python代码,无需写入文件,同时能获取函数返回结果。以下是具体实现方案:

核心思路

  1. 初始化Python解释器;
  2. 创建一个模块对象,将字符串形式的Python代码执行到该模块的命名空间中;
  3. 从模块中提取目标函数(如main)并调用;
  4. 处理函数返回的结果(如将Python列表转换为C++数组/容器);
  5. 清理资源并关闭解释器。

完整代码示例

#include <Python.h>
#include <vector>
#include <cstdio>

int main() {
    // 初始化Python解释器
    if (!Py_Initialize()) {
        fprintf(stderr, "Python解释器初始化失败\n");
        return 1;
    }

    // 定义内嵌的Python脚本字符串
    const char* python_script = R"(
def main():
    # 返回固定大小的Python列表(对应需求中的数组)
    return [10, 20, 30, 40, 50]
)";

    // 创建模块对象(使用__main__作为模块名,也可自定义)
    PyObject* pModule = PyImport_AddModule("__main__");
    if (!pModule) {
        fprintf(stderr, "创建模块失败\n");
        Py_Finalize();
        return 1;
    }

    // 获取模块的命名空间字典
    PyObject* pModuleDict = PyModule_GetDict(pModule);
    if (!pModuleDict) {
        fprintf(stderr, "获取模块命名空间失败\n");
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    // 执行Python字符串代码,将内容加载到模块命名空间
    PyObject* pExecResult = PyRun_String(python_script, Py_file_input, pModuleDict, pModuleDict);
    if (!pExecResult) {
        PyErr_Print(); // 打印Python侧的错误信息
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }
    Py_DECREF(pExecResult); // 执行脚本的返回值无需保留

    // 从模块中获取main函数
    PyObject* pMainFunc = PyDict_GetItemString(pModuleDict, "main");
    if (!pMainFunc || !PyCallable_Check(pMainFunc)) {
        fprintf(stderr, "无法获取可调用的main函数\n");
        if (PyErr_Occurred()) PyErr_Print();
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    // 调用main函数(无参数传递)
    PyObject* pFuncResult = PyObject_CallObject(pMainFunc, NULL);
    if (!pFuncResult) {
        PyErr_Print();
        Py_DECREF(pMainFunc);
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    // 将Python列表转换为C++ vector
    std::vector<int> cpp_array;
    if (PyList_Check(pFuncResult)) {
        Py_ssize_t list_size = PyList_Size(pFuncResult);
        for (Py_ssize_t i = 0; i < list_size; ++i) {
            PyObject* pItem = PyList_GetItem(pFuncResult, i);
            if (PyLong_Check(pItem)) {
                long value = PyLong_AsLong(pItem);
                cpp_array.push_back(static_cast<int>(value));
            } else {
                fprintf(stderr, "列表元素不是整数类型\n");
                Py_DECREF(pFuncResult);
                Py_DECREF(pMainFunc);
                Py_DECREF(pModule);
                Py_Finalize();
                return 1;
            }
        }
    } else {
        fprintf(stderr, "main函数未返回列表类型\n");
        Py_DECREF(pFuncResult);
        Py_DECREF(pMainFunc);
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    // 输出转换后的C++数组
    printf("从Python main()获取的数组:");
    for (int num : cpp_array) {
        printf("%d ", num);
    }
    printf("\n");

    // 清理Python对象资源
    Py_DECREF(pFuncResult);
    Py_DECREF(pMainFunc);
    Py_DECREF(pModule);
    // 关闭Python解释器
    Py_Finalize();

    return 0;
}

关键注意事项

  • Python 3 API适配:你原来的PyString_FromString是Python 2的API,Python 3中需替换为PyUnicode_FromString;
  • 引用计数管理:所有通过Python API创建的对象(除了部分借用引用的情况),都需要用Py_DECREF释放,避免内存泄漏;
  • 编译链接:编译时需要链接Python库,以Linux为例:
    g++ -o embed_python embed_python.cpp $(python3.11-config --cflags --ldflags)
    
    Windows下需配置Python的include和lib路径,链接python311.lib;
  • 参数传递:如果需要给main函数传参,可改用PyObject_CallFunction或PyObject_CallMethod,例如:
    // 传递两个整数参数给main
    PyObject* pArgs = PyTuple_Pack(2, PyLong_FromLong(100), PyLong_FromLong(200));
    PyObject* pFuncResult = PyObject_CallObject(pMainFunc, pArgs);
    Py_DECREF(pArgs);
    

内容的提问来源于stack exchange,提问作者Krohnus Melavea

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:25:28