目录
Windows下Qt调用Python
环境:
win10 64bit
Qt 5.12.0
Python3.6.8
ide:Qt Creator
开发思路:Qt调用python的自定义类并实例化,然后将该对象通过参数传给python脚本处理,最后再传回Qt。软件有跨平台需求,win7以上的环境和中标麒麟系统。
1.准备工作
首先Qt和Python的位数要相同,我的都是64位。
将Python目录下include文件加和libs文件夹都拷到qt工程目录下
Qt Creator工程右键菜单->添加库
选择外部库,点下一步
平台只选windows,库文件选择刚刚拷的libs目录下的python36.lib文件,包含路径选择刚刚拷的include路径,点下一步再点完成就好了。
完成后*.pro文件里面是在下面图片的样子。
编译的时候会报错,先更改include/object.h文件,增加两行代码,下图中标记的地方,原因是python和qt的命名冲突
在#include "Python.h"的前面先引入math.h
编译报错的问题解决了,但是程序会闪退,有两种方法,第一种是环境变量添加python的路径,这个网上多得是不再赘述。
重点是第二种方法,在没有安装python的环境也可以用,将python目录下的Lib文件夹和python36.dll拷到Qt工程debug或release目录下,如下面两张图所示。
2.编写python的自定义类
python自定义类DataTableObject是个二维表对象,但每一列对应不同的位号信息,首列是时间列,数据类型是字符串,大致是这样,截取了部分代码当做示例,然后将这个文件放到debug或release目录下lib文件夹,就是上一步拷的那个文件夹。
datatableobject.py
# -*- coding:utf-8 -*-
import copy
# 行数据对象
class RowCell:
def __init__(self):
self.dataList = list()
def __del__(self):
self.dataList = []
# 位号信息对象
class TagInfoObject:
TYPE_ANALOG = 0
TYPE_SWITCH = 1
TYPE_INTEGER = 2
def __init__(self, name = '', desc = '', unit = '', datatype = TYPE_ANALOG, rangezero = 0, rangefull = 100):
self.name = name
self.desc = desc
self.type = datatype
self.unit = unit
self.rangeZero = rangezero
self.rangeFull = rangefull
# 数据表对象
class DataTableObject:
TYPE_ANALOG = 0
TYPE_SWITCHTYPE_INTEGER = 1
TYPE_SWITCH = 2
def __init__(self):
self.__allData = [RowCell()]
self.__allData.clear()
self.__columnNames = ['']
self.__columnNames.clear()
self.__tagInfoList = [TagInfoObject()]
self.__tagInfoList.clear()
self.__flag = False
... ...
3.C++调用Python的自定义类
DatatableObject::DatatableObject()
{
m_RetStatus = 0;
m_pDataObject = nullptr;
Py_Initialize();
if (!Py_IsInitialized())
{
qDebug() << "python解释器初始化失败";
m_RetStatus = SCRIPT_INIT_FAIL;
return;
}
PyObject *pModule = PyImport_ImportModule("datatable");
PyObject *pClassDict = PyModule_GetDict(pModule);
PyObject *pClassDataTable = PyDict_GetItemString(pClassDict, "DataTableObject");
if (!pClassDataTable)
{
qDebug() << "not found pClassDataTable";
m_RetStatus = SCRIPT_FILE_INVALID;
return;
}
PyObject *pTempClass = PyInstanceMethod_New(pClassDataTable);
m_pDataObject = PyObject_CallObject(pTempClass, nullptr);
Py_DECREF(pTempClass);
Py_DECREF(pClassDataTable);
Py_DECREF(pClassDict);
Py_DECREF(pModule);
}
// 对象销毁
DatatableObject::~DatatableObject()
{
if (Py_IsInitialized())
Py_Finalize();
Py_INCREF(m_pDataObject);
Py_DECREF(m_pDataObject);
}
// 设置脚本文件路径
void DatatableObject::setFilePath(QString path)
{
QFileInfo file(path);
QString filePath = QString("sys.path.append('%1')").arg(file.path() + "/");
PyRun_SimpleString("import sys");
PyRun_SimpleString(filePath.toLatin1().data());
m_ScriptObjectName = file.baseName();
}
***最近调试程序的时候发现闪退,会报找不到标准库的错误。
解决办法很简单,在项目构建设置里添加Lib的路径,然后清除再重新构建即可。
4.生成应用程序
将release目录下的*.exe文件拷到单独文件夹,在qt命令行cd到exe的目录下,再windeployqt xxx.exe
再将release目录下的Lib文件夹和python36.dll拷到exe目录下面,直接运行exe不会报任何错误。
------------以上是windows环境下的操作,下面是linux环境下的操作--------------
中标麒麟下Qt调用Python
环境:
中标麒麟服务器版x86_64 v5.0 虚拟机
Qt 5.9.6
Python3.6.8 64bit
ide:Qt Creator
工程还是上面的工程,外部库配置的时候有点区别。
1.首先配置python的环境和安装必要的依赖
版本低的话要升级openssl
安装python-3.6.8 64bit
安装python3-devel
2.添加外部库
首先要将python3.6安装目录下的lib文件夹拷到qt的debug/release目录下,再将python3安装目录下的include拷到qt工程目录下。
3.再修改pro文件
4.生成应用程序
使用linuxdeployqt打包程序,和windows环境使用方法下相似。
可以参考https://blog.csdn.net/hu626626/article/details/100918455
输入命令linuxdeployqt xxxx -appimage
生成应用程序后再将release/lib目录下的python3.6文件夹拷到exe/lib目录下
5.编写启动程序runApp.sh
需要设置临时环境变量
记录差不多就这些,其他的细节记不清楚了,有时间再写吧。。。