受益于跨平台的特性,Qt生成dll的各种语言调用上体现的淋漓尽致,上篇已经演示了qt生成的无ui的dll及vc如何调用它,本篇将演示vc如何调用qt生成的带ui的dll。
传统观点认为Qt生成的带ui的dll受限于 QApplication 的 exec 方法,这样才能产生消息循环于是只能采用QTWinmigrate中重写DllMain函数,但是仔细看该方案太繁琐和冗余了,于是受上篇启发,进行了以下尝试,果然可以。
一、新建qt widgets项目
因为在qt dll项目中我们不方便调试和布局界面,所以推荐方案是新建一个qt widgets项目。
在该项目中将ui布局好,如下图新建一个mainwindow的项目,没有添加任何一行代码,仅在控件编辑里拖出来两个控件,然后用信号槽关联起来,这样在滑动下面滑块时,上面进度条可以跟着变化。
1、 ui设计器如下;
2、源码如下,如你所见它全部是qt craeator向导建完项目后自动生成的,没有手动改写任何一行代码;
3、切换到Release编译,正常运行;
二、新建一个dll项目
这个步骤,完全按照向导进行即可;
1、新建库项目;
2、注意勾选qt widgets模块;
3、尝试包含QMainWindow.h如果不报错那就可以了;
4、把第一步中新建的widgets项目中的.h .cpp .ui三个文件(注意不需要main.cpp),全部复制到项目目录下并添加到项目中,如下图;
5、在dll项目中,声明一个成员函数,必须是int形参和返回值的函数,然后定义如下;
6、原来main.cpp包含的头文件,也在这里包含上,然后把main函数修改后如下:
//以下为原来main.cpp,可对比以下,其实就是把main函数用一个成员函数换掉,形参稍作变化,让qt的事件循环继续存在
7、也切换到Release,然后构建,最后如图右边,生成了dll和.lib,把除这两个文件外的临时文件全部删除;
8、找到对应编译器的命令行,然后命令在切换到dll所在目录下;
9、qt的命令行,解决带ui的dll还依赖的qt dll,成功后如下图2;
三、VC项目调用
1、新建控制台项目,切到Release x64,生成一个exe,确认项目无误;
2、把上面第9步生成的所有文件复制到vc项目exe输出文件夹里;
3、把9步生成的.lib文件、dll项目所带两个.h(后面复制的不需要),全部复制到vs项目目录下,并把.lib添加到资源,把.h添加到项目里;
4、将两个.h所用到的Qt的头文件直接屏蔽,并把global.h结尾的文件里添加红色框内容如下:
#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
# define Q_DECL_EXPORT __declspec(dllexport)
# define Q_DECL_IMPORT __declspec(dllimport)
#else
# define Q_DECL_EXPORT __attribute__((visibility("default")))
# define Q_DECL_IMPORT __attribute__((visibility("default")))
#endif
5、包含头文件,实例化该类并调用,如下图2可以看到完美的通过VC++正常调用带ui的qt生成的dll;
6、把Release复制到没有编译环境的电脑中,测试,也可正常运行;
总结,至此完成了,vc项目调用qt生成的带ui的dll,它比采用QTWinmigrate中重写DllMain函数的方法更加易于理解和调用。
此项目为了演示没有用线程,因为qt的事件循环机制,事实上应该新建一个线程在线程内部调用更加合理。