A40i使用笔记:qt调用python

一、前言

linux 下qt调用python运算,这里记录一下,有些问题太坑了,也分享出来让大家避坑

二、环境

linux3.10

python3.6.5

三、正文

正常调用步骤

pro引用相关库,用到numpy就安装一个,在引用头文件

LIBS += -L/root/workspace/allwinner/A40i/FCU2401ubuntu16/lichee/MyApp/buildpy3.6.5/lib/ -lpython3.6m
INCLUDEPATH += /root/workspace/allwinner/A40i/FCU2401ubuntu16/lichee/MyApp/buildpy3.6.5/include/python3.6m
DEPENDPATH += /root/workspace/allwinner/A40i/FCU2401ubuntu16/lichee/MyApp/buildpy3.6.5/include/python3.6m

INCLUDEPATH += /root/workspace/allwinner/ubuntuAPP/Python-3.6.5/buildpy3.6.5/lib/python3.6/site-packages/numpy/core/include/numpy

头文件包含

#include <Python.h>
#include <Python.h>
#include <QApplication>
#include <iostream>
#include <ndarrayobject.h>

初始化和运行

    Py_SetPythonHome(L"/usr/local/python3");//这行代码要写在最前面,不然会出问题

// 初始化python解释器.C/C++中调用Python之前必须先初始化解释器
    Py_Initialize();

 QVector<double> cgq_sd_speed[4];//4通道速度数值
    qDebug()<<"cgq_jsd_speed group size is "<<QString::number(cgq_jsd_speed[0].size());
    //1、初始化使用的变量
    PyObject* pModule = NULL;
    PyObject* pFunc = NULL;
    PyObject* pRet  = NULL;
    //2、初始化python系统文件路径,保证可以访问到 .py文件
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('/root/workspace/')");//      './'
    //3、调用python文件名。当前的测试python文件名是 myadd.py
    pModule = PyImport_ImportModule("test0611");// 在使用这个函数的时候,只需要写文件的名称就可以了。不用写后缀。
    if (!pModule)qDebug()<<"PyImport_ImportModule err";
//    else qDebug()<<"PyImport_ImportModule ok";
    //4、调用函数
    pFunc = PyObject_GetAttrString(pModule, "acc_demo");//第二个参数是python文件定义的主函数名
    if(!pFunc)qDebug()<<"PyObject_GetAttrString err";
//    else qDebug()<<"PyObject_GetAttrString ok";
    //5、传递参数,新建一个变量,长度为传入参数个数,然后一次将数据传入
    //方式一
    // 所有像素点的数量,要乘以通道数
//    int nElem = 100;
    // 创建与像素个数大小相同的数组
//    uchar* m = new uchar[nElem];
    // 将Mat格式矩阵数据复制到新建的数组中
//    memcpy(m, Dataall.data(), nElem * sizeof(uchar));
//    int dims[1];
//    dims[0] = nElem;
    // 生成包含这个多维数组的PyObject对象,使用PyArray_SimpleNewFromData函数,第一个参数3表示维度,第二个为维度数组Dims,第三个参数指出数组的类型,第四个参数为数组
//    PyObject *PyArray  = PyArray_SimpleNewFromData(1,dims,NPY_UINT8,/*(void*)*/m);
//    PyTuple_SetItem(args, 0, PyArray);  //参数设置

    //方式二
//    PyObject* args = PyTuple_New(4);//输入参数数量
//    PyObject* pList1 = PyList_New(0);
//    PyObject* pList2 = PyList_New(0);
//    PyObject* pList3 = PyList_New(0);
//    PyObject* pList4 = PyList_New(0);
    qDebug()<<cgq_jsd_speed[3];
//    for (int i = 0; i < cgq_jsd_speed[0].size(); i++){//cgq_jsd_speed[0].size()
//        PyList_Append(pList1, Py_BuildValue("i", PyFloat_FromDouble(cgq_jsd_speed[0][i])));
//        PyList_Append(pList2, Py_BuildValue("i", PyFloat_FromDouble(cgq_jsd_speed[1][i])));
//        PyList_Append(pList3, Py_BuildValue("i", PyFloat_FromDouble(cgq_jsd_speed[2][i])));
//        PyList_Append(pList4, Py_BuildValue("i", PyFloat_FromDouble(cgq_jsd_speed[3][i])));
//    }
//    PyTuple_SetItem(args, 0, pList1);  //参数设置1
//    PyTuple_SetItem(args, 1, pList2);  //参数设置1
//    PyTuple_SetItem(args, 2, pList3);  //参数设置1
//    PyTuple_SetItem(args, 3, pList4);  //参数设置1
    PyTuple_SetItem(args, 4, Py_BuildValue("d", /*(double)(1/Datafreq/100)*/0.01)); //4---序号 d---double
//    pRet = PyEval_CallObject(pFunc, args);//传入参数

    //方式三 ChatGPT
    PyObject* args = PyTuple_New(5);//输入参数数量
    PyObject* pList1 = PyList_New(Datapoint);
    PyObject* pList2 = PyList_New(Datapoint);
    PyObject* pList3 = PyList_New(Datapoint);
    PyObject* pList4 = PyList_New(Datapoint);
    for (int i = 0; i < Datapoint; i++){//cgq_jsd_speed[0].size()
        PyList_SetItem(pList1, i, PyFloat_FromDouble(cgq_jsd_speed[0][i]));
        PyList_SetItem(pList2, i, PyFloat_FromDouble(cgq_jsd_speed[1][i]));
        PyList_SetItem(pList3, i, PyFloat_FromDouble(cgq_jsd_speed[2][i]));
        PyList_SetItem(pList4, i, PyFloat_FromDouble(cgq_jsd_speed[3][i]));
    }
    PyTuple_SetItem(args, 0, pList1);  //参数设置1
    PyTuple_SetItem(args, 1, pList2);  //参数设置2
    PyTuple_SetItem(args, 2, pList3);  //参数设置3
    PyTuple_SetItem(args, 3, pList4);  //参数设置4
    double shijianjiange=QString::number((double)(0.01/(double)Datafreq),'f',7).toDouble();
    PyTuple_SetItem(args, 4, Py_BuildValue("d", shijianjiange)); //4---序号 d---double
    pRet = PyEval_CallObject(pFunc, args);//传入参数

    //6、接收python计算好的返回值
    //方式一
//    if(pRet){
//        PyObject* repr = PyObject_Repr(pRet);
//        PyObject* rstr = PyUnicode_AsEncodedString(repr,"utf-8","strict");
//        char *p=PyBytes_AsString(rstr);
//        qDebug()<<"pyres1="<<p;
//        qDebug()<<cgq_sd_speed[0];
//    }
//    else
//        qDebug()<<"PyEval_CallObject err";

    //方式二 ChatGPT
    PyArrayObject *pNumPyArray = reinterpret_cast<PyArrayObject *>(pRet);
    if (pNumPyArray){
        double *pData = reinterpret_cast<double *>(PyArray_DATA(pNumPyArray));
        for(int i = 0; i < 4; i++){
            for (int j = 0; j < Datapoint; j++) {
                cgq_sd_speed[i].append(pData[i * cgq_jsd_speed[0].size() + j]);
            }
        }
    }
    else{
        qDebug()<<"sudu max value:0 somewhere is wrong! PyEval_CallObject err";
    }
 //释放数据缓存
    PyGC_Collect();//垃圾回收函数,否则无法多次调用,多次调用内存会急剧上升直至崩溃
    Dataall.clear();//清空原始数据数组,等待下次采集分析

//     撤销Py_Initialize()和随后使用Python/C API函数进行的所有初始化
    Py_Finalize();

将python文件放在与qt程序同级目录就行了

下面分享大坑解决办法:


大坑1:程序手动执行./xxx可以执行,调用到python时也正常,但是在脚本里开机自动执行,在调用到python时就提示错误,如下

[   20.618186] rc.local[2231]: Could not find platform independent libraries <prefix>
[   20.619269] rc.local[2231]: Could not find platform dependent libraries <exec_prefix>
[   20.619911] rc.local[2231]: Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
[   20.651721] rc.local[2231]: Fatal Python error: Py_Initialize: Unable to get the locale encoding

或者PyImport_ImportModule err或者Py_Initialize err这种

问题就是环境配置问题,需要在qt初始化前配置一下python的环境,如果环境配置不对会提示初始化错误,环境配置正确了还没完事,到PyImport_ImportModule函数时会报错,这时要将

 PyRun_SimpleString("sys.path.append('/root/workspace/')");这句话设置为python程序的绝对路径

默认是    PyRun_SimpleString("sys.path.append('./')");但是不知道为什么开机自动执行脚本在调用程序执行到这里就失败,搞了一天一宿才解决这个问题,心累。

大坑1 end


大坑2:

四、结语

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大桶矿泉水

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值