接到任务要做一个既可以在Qt下又可以在VC,C#下使用,且含有界面的dll封装形式的组件, 纠结了大概四五天的样子,找遍了整个互联网,这方面的资料太少了,仅有一两个被转载了n多遍的没有新意的介绍,且实用性不强,本人经过数天摸索成功在VC下调用Qt编译的带界面的DLL。
首先强调一下环境:
操作系统: win8
VS 版本: VS2010
Qt 版本: qt-opensource-windows-x86-mingw482_opengl-5.3.0.exe
qtwinmingrate版本: qt-solutions-ov3r1oads-qt-solutions 此版本较为新,2.8 在Qt5下用不了。
下载地址:https://qt.gitorious.org/qt-solutions/ov3r1oads-qt-solutions/source/80592b0e7145fb876ea0e84a6e3dadfd5f7481b6:
参考:1,http://blog.csdn.net/normallife/article/details/5397980
2, http://www.rebaoxian.com/28649.html
3,http://qimo601.iteye.com/blog/1675575
参考十分有限而且粗略,不适合新手来做,没有例子,没有详细的代码。且所用Qt版本老旧
我的工作
1 首先安装好Qt5.3, 这个不用多说。
2 下载下来qt-solutions-ov3r1oads-qt-solutions 解压后进入D:\qt-solutions-ov3r1oads-qt-solutions\qtwinmigrate\examples\qtdll 目录,该目录下面有qtdll.pro工程文件 用 qt5.3打开该文件。
3 测试是否可以进行编译,上述文件后在Qtcreater 中构建,或者编译该项目,编译通过后会弹出下图所示自定义执行档对话框,此种情况很正常,因为是dll 项目无程序入口qt让指定入口,关闭即可。第一次编译出现此界面,随后就不会出了,关闭后找到dll生成目录我的机子上为D:\qt-solutions-ov3r1oads-qt-solutions\qtwinmigrate\examples\build-qtdll-Desktop_Qt_5_3_0_MinGW_32bit-Debug\debug 如果成功该目录下会有我们期待已久的qtdialog.dll。
4 上述步骤顺利的话说明你的可以往下进行了。我开始的理解是这个qtdialog.dll 即使我所需要的,将它拷贝出来就可以用了,可实践证明我想多了。用VS2010建了一个MFC工程进行测试,测试例子很简单就一个基于对话框的界面上面放一个按钮,按钮事件是调用该dll.
HMODULE mod = LoadLibrary( "qtdialog.dll" );
DWORD err= GetLastError();
if ( mod ) { typedef BOOL(*pShowDialog)(HWND parent);
pShowDialog showDialog = (pShowDialog)GetProcAddress( mod, "showDialog" );
if ( showDialog )
showDialog( theApp.m_pMainWnd->m_hWnd );
FreeLibrary( mod );
} else {
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
接下来就是一个痛苦的过程了,
问题1:无论如何也不能加载qtdialog.dll ,mod 的值始终都是0, 工程目录下明明有该dll文件。
解决办法: 调用 LoadLibrary();后立马调用GetLastError()得到错误码,分析错误码。
错误码为126 意思是无法加载相应模块。这可怎么办呢?后来想想是不是dll依赖的一些qt的库没有复制过来导致的,遂使用Depends.exe查看该dll的依赖项,果不其然依赖挺多的后将各个依赖项在qt的安装目录下通过搜索找到放到MFC工程目录下。找到这些后还会提示有依赖项,总之把所有的依赖项添加完毕我一共添加了下图那么多可能有些是多余的。当然这是debug版本下的都带了个d.因为这个依赖项的问题搞了整整一天!
问题2:依赖问题解决了也能载入dll了而且mod不为空,而且能够得到showDialog()函数的地址 但是一直出这样的错误,太坑爹了,不知道什么原因呀!!
解决办法:首先尝试了各种方法,下载旧版本的VC运行时,修复dll ............总之就差重装系统了,没有解决,最后想想是不是这种调用方法有问题?
按照参考2 中的方法试一下。
打开qtdll工程,打开源文件中的main.cpp 备用,然后右键单击qtdll工程添加新文件“qt界面设计师类”继承与mainwindow 类当然也可以是其他的界面类,
在界面上随意放置两个组件,如button,label等
然后将main函数中的下面一段:
//extern "C" __declspec(dllexport) bool showDialog( HWND parent )
//{
// QWinWidget win( parent );
// win.showCentered();
// QMessageBox::about( &win, "About QtMfc", "QtMfc Version 1.0\nCopyright (C) 2003" );
// return TRUE;
//}
换成
extern "C" __declspec(dllexport)int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyJieMian w;
w.show();
return a.exec();
}
重新编译通过。重新将生成的dll文件拷贝到MFC测试工程中
5 测试成功
将MFC按钮响应程序改为下述代码
void CMFCDLLDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
HMODULE mod = LoadLibrary( "qtdialog.dll" );
DWORD err= GetLastError();
if ( mod ) {
typedef int (*Mymain)(int argc, char *argv[]);
Mymain mmain= (Mymain)GetProcAddress(mod,"main");
char* b="abc";
char**a=&b;
mmain(0,a);
FreeLibrary( mod );
} else {
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
}
按下MFC中的按钮奇迹出现了,虽然丑了点但是还是出现了Qt下设计好的界面了。