- 主题:Python如何调用基于Qt库的dll?
有一个独立的基于Qt库编写的dll,完成了数据读取、前处理等功能,最后输出一个结构
体,
结构体包含几个QVector<double>的字段。现在想在一Python独立程序里调用这个dll,
请教
该如何做? 需要在Python里装PySide2吗? 有没有推荐的参考帖子?
Qt版本是5.15.2,Python是3.7.9。
--
FROM 218.107.204.*
何不先序列化一下再传?
【 在 callmebbser 的大作中提到: 】
: 有一个独立的基于Qt库编写的dll,完成了数据读取、前处理等功能,最后输出一个结构
: 体,
: 结构体包含几个QVector<double>的字段。现在想在一Python独立程序里调用这个dll,
: ...................
--
FROM 180.174.48.*
数据量比较大,前处理好存起来需要时间,Python再读进来也需要时间,而且还不连贯。
【 在 missdeer 的大作中提到: 】
: 何不先序列化一下再传?
--
FROM 119.233.243.*
你用 c++ 写个包装程序,把 QVector<double> 的第一个元素的内存地址拿出来传给 python 去处理就行了啊。
QVector<double> bigData;
传:
&bigData[0], bigData.size()
两个数据,python 就能够使用 ctypes 处理了。
【 在 callmebbser 的大作中提到: 】
: 有一个独立的基于Qt库编写的dll,完成了数据读取、前处理等功能,最后输出一个结构
: 体,
: 结构体包含几个QVector<double>的字段。现在想在一Python独立程序里调用这个dll,
: ...................
--
FROM 183.253.146.*
谁来负责删数据呢?处理不好的话容易内存泄露吧
【 在 hgoldfish 的大作中提到: 】
: 你用 c++ 写个包装程序,把 QVector<double> 的第一个元素的内存地址拿出来传给 python 去处理就行了啊。
: QVector<double> bigData;
: 传:
: ...................
--
FROM 117.136.0.*
https://wiki.qt.io/Qt_for_Python/Shiboken ?
把qt库转成python?
【 在 callmebbser 的大作中提到: 】
: 有一个独立的基于Qt库编写的dll,完成了数据读取、前处理等功能,最后输出一个结构
: 体,
: 结构体包含几个QVector<double>的字段。现在想在一Python独立程序里调用这个dll,
: ...................
--
FROM 195.1.63.*
pybind
--
FROM 223.70.157.*
谢谢楼上各位提供的信息,摸索了几天,终于有进展了。
我的场景是:一个基于Qt开发的在Windows 10 64位操作系统里运行的数据处理软件,不
同的数据处理分成不同的Qt插件工程开发,一些插件是纯Qt C++开发,一些插件是Qt C
++调用Python编写PyInstaller打包的外部程序来处理(比如深度学习),处理结果输出
到文件再通知Qt插件显示。数据文件和预处理是另外一个Qt软件的生成和处理的,这个
Qt软件提供了读取和预处理的dll。因此,Qt插件工程调用这个dll是毫无问题的。问题
存在于Python编写打包的外部程序。Qt插件工程可以先调用dll读取数据并预处理好,写
到文件中,然后调用Python程序来进一步处理。但若要处理数据量比较大,耗时长,用
户等待时间长,体验感差。在Python程序里调用Qt dll,则可以读取、预处理、深度学
习一条龙,是最合理的方式。
Shiboken、PySide2、Boost.Python、pybind11这几个都需要编译,写中间C/C++程序,
比较啰嗦复杂,搞不来。
Python自带的ctypes模块用起来相对简单、简洁。
ctypes只支持C语言接口,不支持C++接口,因此,把Qt dll的功能简单写个C函数导出来
。
extern "C" __declspec(dllexport) void loadData(const char *datafile, int *le
ngth, double **x, double **y) {
MyDataStruct data = QtDllClass::staticReadAndProcessMethod(QString(dataf
ile));
int n = data.x.size(); // x是个QVector<double>类型的字段
double *vx = new double[n];
double *vy = new double[n];
memcpy(vx, data.x.data(), n*8);
memcpy(vy, data.y.data(), n*8);
*x = vx;
*y = vy;
*length = n;
}
建立一个Qt Library项目,引用Qt的读和预处理数据的dll,把上面的C函数放进去,最
后构建出一个LoadDataLib4Py.dll。
然后在Python里用ctypes如下调用这个LoadDataLib4Py.dll。
import ctypes
INT_PTR = ctypes.POINTER(ctypes.c_int)
DBL_PTR_PTR = ctypes.POINTER(ctypes.POINTER(ctypes.c_double))
dll = ctypes.cdll.LoadLibrary('LoadDataLib4Py.dll')
loadData = dll.loadData
loadData.argtypes = [ctypes.c_char_p, INT_PTR, DBL_PTR_PTR, DBL_PTR_PTR]
datafile = 'D:/Temp/xxx/aa.dat'.encode('utf-8')
length = ctypes.c_int(0)
x = ctypes.pointer(ctypes.pointer(ctypes.c_double(0.0)))
y = ctypes.pointer(ctypes.pointer(ctypes.c_double(0.0)))
loadData(datafile, ctypes.pointer(length), x, y)
for i in range(length.value):
print(f'data {i} = {x[0][i]}, {y[0][0]}')
C代码和Python代码是凭印象手写的,只是个大概,不保证能运行。真正可运行的代码在
公司电脑上。
我一开始没直接调用真实的Qt dll,而是简单地写了个读写文本数据文件的moc dll,把
C代码和Python都调试成功通过。
等换上真正的数据读取和预处理的Qt dll,却碰上了幺蛾子事件。
真实的Qt dll不但调用了另外的dll,而且还用到了Qt的sql模块,而Qt的QSqlDataBase
是Qt插件式的,需要QCoreApplication实例加载数据库驱动。我试了在C函数里实例化Q
CoreApplication,但Python代码里ctypes的LoadLibrary()执行后,还是提示没有数据
库驱动。一番搜索后,在C函数开头加上一句QCoreApplication::addLibraryPath("./p
lugins"),Python代码居然执行成功了!
目前是Python代码文件和Qt的库dll,自己写的dll等放在同一个目录下,调试成功了。
还没有用PyInstaller把Python代码打包,不知打包后的exe执行会不会正常。
内存泄漏问题目前也没有测试。
【 在 wego 的大作中提到: 】
: pybind
--
FROM 119.233.183.*