C++调用Python

发布于:2025-03-29 ⋅ 阅读:(30) ⋅ 点赞:(0)

Python安装

地址: python官网
官网

可以根据需要下载对应的版本。

调用python

python测试脚本

# my_script.py
import sys
import json

def calculate(a, b):
    return a * b + 10  # 示例计算逻辑

if __name__ == "__main__":
    # 从命令行参数读取 JSON 字符串
    try:
        args = json.loads(sys.argv[1])
        a = args['a']
        b = args['b']
        result = calculate(a, b)
        # 输出 JSON 格式结果
        print(json.dumps({"result": result}))
    except Exception as e:
        print(json.dumps({"error": str(e)}), file=sys.stderr)
        sys.exit(1)

调用方式:

脚本直接调用

通过写python成脚本,运行python解释器并运行对应的脚本,执行对应的任务,如果是跟自己程序不需要进行通讯的,这种方式是最好的,不涉及参数的传输。
通过json结构来传入程序运行数据。并通过接收终端打印信息解析回数据。

#include <QProcess>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDebug>

void callPythonScript() {
    QProcess pythonProcess;
    
    // 定义参数(例如 a=5, b=3)
    QJsonObject params;
    params["a"] = 5;
    params["b"] = 3;
    QString jsonArgs = QJsonDocument(params).toJson(QJsonDocument::Compact);

    // 启动 Python 进程
    pythonProcess.start("python", QStringList() << "my_script.py" << jsonArgs);
    
    if (!pythonProcess.waitForFinished()) {
        qDebug() << "Python 进程执行超时或出错";
        return;
    }

    // 读取标准输出
    QByteArray output = pythonProcess.readAllStandardOutput();
    QJsonDocument resultDoc = QJsonDocument::fromJson(output);
    
    if (resultDoc.isObject()) {
        QJsonObject resultObj = resultDoc.object();
        if (resultObj.contains("result")) {
            int result = resultObj["result"].toInt();
            qDebug() << "计算结果:" << result;  // 输出:计算结果:25 (5*3+10)
        } else if (resultObj.contains("error")) {
            qDebug() << "Python 错误:" << resultObj["error"].toString();
        }
    } else {
        qDebug() << "无法解析 Python 输出:" << output;
    }
}

通过嵌入Python调用

python提供了C语言的API,可以通过C语言来调用Python。

#include <Python.h>
#include <QCoreApplication>
#include <QDebug>

void callEmbeddedPython() {
    Py_Initialize();

    // 1. 添加脚本目录到 sys.path
    QString scriptDir = "D:/test";
    PyRun_SimpleString("import sys");
    PyRun_SimpleString(qPrintable(QString("sys.path.append('%1')").arg(scriptDir)));

    // 2. 导入模块(模块名 = 文件名不含 .py)
    PyObject *pModule = PyImport_ImportModule("my_script");
    if (!pModule) {
        PyErr_Print();
        qDebug() << "模块导入失败,请检查:"
                 << "\n- 文件路径: " << scriptDir + "/my_script.py"
                 << "\n- Python 环境: 当前解释器版本为 " << Py_GetVersion();
        Py_Finalize();
        return;
    }

    // 3. 调用函数
    PyObject *pFunc = PyObject_GetAttrString(pModule, "calculate");
    if (pFunc && PyCallable_Check(pFunc)) {
        PyObject *pArgs = PyTuple_New(2);
        PyTuple_SetItem(pArgs, 0, PyLong_FromLong(5));
        PyTuple_SetItem(pArgs, 1, PyLong_FromLong(3));
        PyObject *pResult = PyObject_CallObject(pFunc, pArgs);
        if (pResult) {
            qDebug() << "[嵌入式] 结果:" << PyLong_AsLong(pResult);
            Py_DECREF(pResult);
        }
        Py_DECREF(pArgs);
        Py_DECREF(pFunc);
    } else {
        PyErr_Print();
        qDebug() << "函数 calculate 未找到或不可调用";
    }

    Py_DECREF(pModule);
    Py_Finalize();
}

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    callEmbeddedPython();
    return a.exec();
}

异常处理

1.如果qt中引入#include <Python.h>会出现报错

报错
因为用了slots变量,这个在qt中是关键字,需要把这个变量换一个名字就可以了。
在这里插入图片描述

2. 通过嵌入Python调用时候,直接运行脚本是有问题的

需要把这个脚本引入到对应的模块中,才能调用,否则就会报错。