谢谢楼上各位提供的信息,摸索了几天,终于有进展了。
我的场景是:一个基于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.*