一、前言
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: