外部程序调用Qt5带界面的dll
2016-08-12 09:37
337 查看
一、 主要参考
参考1:http://blog.csdn.net/libin88211/article/details/38183791参考2:http://blog.csdn.net/suifenghuidong/article/details/12032077
参考3:http://blog.csdn.net/tingsking18/article/details/4967172
参考4:http://bbs.csdn.net/topics/370053884
二、 背景及环境
目标:在MFC、VC++控制台程序里能调用Qt5编写的带界面的DLL。Qt5直接编译的DLL在MFC、VC++控制台程序里是不能调用的,为了实现上述目标,开始在度娘上查找资料。首先发现了解决方法是qtwinmigrate,但正如参考1中所写,想找一个现成可用的资料真是不容易。后来把能查出的基本都浏览了一遍,经过一些曲折的学习测试,终于基本实现。所以还是梳理下,便于之后查看,也给有需要的小伙伴们提供一个参考。
本人环境:
软件 | 版本 |
Qt | qt-opensource-windows-x86-mingw492-5.6.0.exe |
Visual Studio | VS2010 |
QtWinmigrate | https://github.com/qtproject/qt-solutions |
三、 具体使用
3.1 编译qtwinmigrate
将下载好的qtwinmigrate解压,用Qt Creator打开…\qtwinmigrate\examples\qtdll\qtdll.pro,然后在Release模式下构建。图1 qtdll及构建
构建完成后,会在…\qtwinmigrate\examples\build-qtdll-Desktop_Qt_5_6_0_MinGW_32bit-Release\release下生成qtdialog.dll 。
3.2 找到DLL的依赖项
上步中生成了DLL,但是还不能直接拿去使用,此时LoadLibrary是加载不上的,因为还需要其依赖的Qt库。网上有些使用DependencyWalker等软件来找DLL依赖项,当然可以,但是过于麻烦。这里采用Qt官方开发环境里自带的工具:windeployqt.exe。如我安装的5.6版本可以在Qt安装目录…\5.6\mingw49_32\bin下找到。
具体使用方法:
先将上步生成的qtdialog.dll 复制到一个新建文件夹,如D:\MyQtDLL。在开始菜单中打开Qt命令行,在命令行中定位到DLL相应目录,执行“windeployqt qtdialog.dll”。此时qtdialog.dll的依赖项便自动copy到其目录下了。
这里有些依赖项可能用不到,比如translations文件夹,删除就行。
图2 打开Qt命令行
图3 使用Qt命令行
图4 qtdialog.dll及其依赖项
3.3 调用Qt5编译的DLL
MFC或者VC++控制台程序在调用Qt5编译的DLL时,需要将上步中qtdialog.dll所在文件夹内所有内容复制到工程编译的exe文件夹内。1. MFC调用
为测试,用VS2010新建一个MFC对话框程序,简单地在界面上放一个按钮,并在按钮点击事件中加载DLL,弹出Qt5的DLL的界面。
void XXX::OnBnClickedButton1() { const char* dllName = "qtdialog.dll"; HMODULE hDLL = LoadLibrary(dllName); if (hDLL != NULL) { typedef bool(*pShow)(HWND parent); pShow fp1 = pShow(GetProcAddress(hDLL, "showDialog")); if (fp1 != NULL) { fp1(theApp.m_pMainWnd->m_hWnd); } FreeLibrary(hDLL); } else { CString strInfo; strInfo.Format("Cannot Find %s", dllName); MessageBox(strInfo); } }
记住运行前将qtdialog.dll所在文件夹内的全部内容复制到工程编译的exe文件夹内。编译成功后,运行如下如
图5 MFC调用qtdialog.dll
2. 控制台程序调用
#include <iostream> #include <Windows.h> using std::cout; using std::endl; int main() { const char* dllName = "qtdialog.dll"; HMODULE hDLL = LoadLibrary(dllName); if (hDLL != NULL) { typedef bool(*pShow)(HWND parent); pShow fp1 = pShow(GetProcAddress(hDLL, "showDialog")); if (fp1 != NULL) { //ShowWindow(GetConsoleWindow(), SW_HIDE); fp1(GetConsoleWindow()); } FreeLibrary(hDLL); } else { cout << "Cannot Find " << dllName << endl; } return 0; }
图6 控制台调用qtdialog.dll
3.4 修改qtwinmigrate,加载自写界面
上面例子中直接使用了qtwinmigrate中自带的QMessageBox,这里将其修改下变为一个自己写的界面。随便用Qt Creator新建一个Dialog,如这里TestDlg:
图7 新建TestDlg
将TestDlg的头文件和源文件复制到qtdll目录下,并在Qt Creator中qtdll项目上右键添加进来。
图8 将TestDlg文件复制到qtdll下并在工程中添加
此时修改接口函数为:
extern "C" __declspec(dllexport) bool showDialog( HWND parent ) { QWinWidget win( parent ); win.showCentered(); CMyDialog mydlg(&win); mydlg.exec(); return TRUE; }
然后重新构建,同上步骤。此时MFC、VC++控制台的调用结果:
图9 MFC调用qtdll自写界面
图10 控制台调用qtdll自写界面
四、 其他问题
4.1 接口函数问题 int main(int argc, char *argv[]) ?
在参考1和4中指出用int main(int argc, char *argv[]) 做接口函数,并在其中创建QApplication对象。接口函数:
extern "C"__declspec(dllexport) int main(int argc, char *argv[]) { QApplication a(argc, argv); CTestDialog w; w.show(); return a.exec(); }
测试:
HMODULE hDLL = LoadLibrary(dllName); if (hDLL != NULL) { typedef bool(*pShow)(HWND parent); typedef int(*pMain)(int, char *[]); pMain fMain =pMain(GetProcAddress(hDLL, "main")); if (fMain != NULL) { fMain(0, 0); } FreeLibrary(hDLL); }结合源码和参考3可知其实QApplication对象在QmfcApp::pluginInstance已经创建。并且QMfcApp::pluginInstance(hInstance)提供了Qt和MFC消息循环共同工作的机制。因此个人觉得采用showDialog中QWinWidget方式更好些。
对于3.4的小例子,测试发现使用发现两种方法都可以。但是测试自写的一个更复杂的界面时发现,多次点击按钮加载DLL时,采用main接口函数会出现异常崩溃现象,如下图:
图11 main接口发生异常情况
相关文章推荐
- QT编写DLL给外部程序调用,提供VC/C#/C调用示例(含事件)
- QT编写DLL给外部程序调用,提供VC/C#/C调用示例(含事件)
- QT编写DLL给外部程序调用,提供VC/C#/C调用示例(含事件)
- 【转】将QT开发的界面程序封装成DLL,在VC中成功调用
- QT编写DLL给外部程序调用,提供VC/C#/C调用示例(含事件)
- ASP编写一个网页界面,页面中设置按钮,按钮能够调用外部命令行程序
- 将QT开发的界面程序封装成DLL,在VC中成功调用
- .net WinForm程序中调用Visual Studio IDE 中数据连接配置界面 (一个DLL搞定)
- vs2012 调用外部代码问题 打开项目一直加载外部dll是程序中断!!
- QT编写DLL给外部程序调用,提供VC/C#/C调用示例(含事件)
- 将QT开发的界面程序封装成DLL,在VC中成功调用(必须有消息循环,所以使用了QTWinmigrate,附CSDN可下载的Demo)
- Dll调用主程序(客户端、外部程序、宿主)函数的实现
- QT调用dll、外部程序调用QT的dll.md
- QProcess调用外部程序不显示界面
- 【转】将QT开发的界面程序封装成DLL,在VC中成功调用
- 将QT开发的界面程序封装成DLL,在VC中成功调用
- MSsql 增删改某个表时,用触发器调用DLL通知外部窗体程序
- QT编写DLL给外部程序调用,提供VC/C#/C调用示例(含事件)good
- 在JAVA中调用外部可执行程序
- C#中利用process类调用外部程序以及执行dos命令