当前位置:文档之家› Qt显式调用dll

Qt显式调用dll

Qt显式调用C++写的dll这些天在做一个工程,要用到Qt,所以特别研究了一下Qt显式调用链接库的问题。

隐式调用就不那么想用了,个人感觉隐式调用既浪费内存,造成程序启动速度极慢,又容易造成链接错误(本人在ogre中深受链接错误之苦),所以只用了显式调用。

以前只试过在MFC 中显式调用dll,在Qt上还没试过。

其实细细研究一下,相对于MFC的调用来说,Qt的调用也是大同小异的。

在这里分享一下。

首先用VS写一个dll先(名字为QtDllTest)。

写dll最大的问题就是解决导出函数重命名问题。

其中解决方法是多种多样的。

本人只用自己最常用一种——用模块定义文件.def。

第一步,写一个dll,简单写一个测试加法函数的:int add(int a,int b){return a+b;}之后添加一个模块定义文件QtDllTest.def:LIBRARY "QtDllTest"EXPORTSadd之后顺利生成dll.现在可以利用dll函数导出工具DLL Export Viewer查看刚才生成的dll中的导出函数:发现,导出函数名字没有乱码,说明导出函数正常。

现在,就以这个dll为例来试着用Qt调用。

新建一个名为QtDllTestDemo的Qt Application:默认,下一步继续下一步:Finish就行了。

反正一切默认就行。

在ui界面中加入一个pushButton(ObjectName:CalButton,Text:Calculate),一个Label 控件(Text:Result),一个lineEdit控件(ObjectName:Result),主要是在点击按钮后调用dll并计算把计算结果显示在文本框中,如下图所示:为了顺利使用dll,我们要在qtdlltestdemo.cpp开始包含这个东西:#include<QLibrary> 下面给pushButton添加click响应事件:void QtDllTestDemo::on_CalButton_clicked(){QLibrary lib("QtDllTest.dll");if (lib.load()){typedef int(*AddFunction)(int a,int b);AddFunction Add=(AddFunction)lib.resolve("add");if (!Add){ui.Result->setText("Failed!");}else{int m;m=Add(1,1); //来个计算1+1QString str=QString("%1").arg(m);ui.Result->setText(str);}}else{ui.Result->setText("Failed!");}}之后生成程序,复制在开始生成的dll文件到QtDllTestDemo的Debug或者Release目录中运行,点击“Calculate"按钮,发现已经成功调用:其实和MFC的调用也就差那么一两句话,真可谓大同小异。

导出类中函数亦如此。

Windows下gcc以及Qt的DLL文件调用之总结2009-06-12 10:42:58.0 来源:e800技术客关键词:Windows gcc Qt DLL调用DLL与LIB的区别:1.DLL是一个完整程序,其已经经过链接,即不存在同名引用,且有导出表,与导入表lib 是一个代码集(也叫函数集)他没有链接,所以lib有冗余,当两个lib相链接时地址会重新建立,当然还有其它相关的不同,用lib.exe就知道了;2.在生成dll时,经常会生成一个.lib(导入与导出),这个lib实际上不是真正的函数集,其每一个导出导入函数都是跳转指令,直接跳转到DLL中的位置,这个目的是外面的程序调用dll时自动跳转;3.实际上最常用的lib是由lib.exe把*.obj生成的lib。

(引用这里)Qt 想调用DLL怎么办呢?最先想到的是直接调用试试看:包含头文件,并把DLL文件拷到当前目录下,调用声明的函数,结果链接时和预想的一样出错了。

修改Makefile.debug,的链接选项也不行。

Windows里的gcc调编译时用的库是和Linux一样的.a文件。

其实,上面用VC直接调用DLL的方法,在Windows里其实叫“隐式链接”,相对的叫“显式链接”,可以参考CSDN的解释。

Qt调用DLL方法一:使用Win32 API在显式链接下,应用程序必须进行函数调用以在运行时显式加载DLL。

为显式链接到DLL,应用程序必须:? 调用LoadLibrary(或相似的函数)以加载DLL 和获取模块句柄。

? 调用GetProcAddress,以获取指向应用程序要调用的每个导出函数的函数指针。

由于应用程序是通过指针调用DLL 的函数,编译器不生成外部引用,故无需与导入库链接。

? 使用完DLL 后调用FreeLibrary。

例如:typedef UINT (CALLBACK* LPFNDLLFUNC1)(DWORD,UINT);HINSTANCE hDLL; // Handle to DLLLPFNDLLFUNC1 lpfnDllFunc1; // Function pointerDWORD dwParam1;UINT uParam2, uReturnV al;hDLL = LoadLibrary(”MyDLL”);if (hDLL != NULL){lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,“DLLFunc1″);if (!lpfnDllFunc1){// handle the errorFreeLibrary(hDLL);return SOME_ERROR_CODE;}else{// call the functionuReturnVal = lpfnDllFunc1(dwParam1, uParam2);}}需要说明的是,typedef UINT (CALLBACK* LPFNDLLFUNC1)(DWORD,UINT);是声明想要调用的函数指针,这个函数的参数必须和DLL里面的一样。

DLLFunc1是DLL里面的“实际的函数名”,必须和头文件里面声明的一样,否则将会调用失败。

使用需要加Windows.h 头文件。

Windows里的Qt是用Mingw GCC来编译,而Mingw GCC可以支持Win32的API。

使用时并不需要包含头文件。

这个方法没有实际验证,理论上是可以的。

Qt调用DLL方法二:使用Qt的API对于调用DLL的方法,Qt原来本身就有相应的类来实现,用起来和Win32的步骤差不多。

下面是代码,已经编译通过。

在控制台依次输入qmake –project、qmake、nmake,即可。

#include#include#include//动态链接不需要包含LTM8000D.h头文件typedef int ( *pcom_open)(int , int , int ); //定义函数指针int main(int argc, char *argv[]){int ret; //函数返回值int port=1; //端口int baud=0; //波特率int rtsdtr=0; //串行口485方向控制设置:QApplication a(argc, argv);QLabel label1(”label-1″); //显示打印信息,将就着用了。

QLabel label2(”label-2″);QLibrary mylib(”LTM8000D.DLL”);if(mylib.load()){label1.setText(”load DLL success!…”);pcom_open open=(pcom_open)mylib.resolve(”ltm_com_open”); //“ltm_com_open”为DLL包含的实际函数名,必须实际存在if(open){ret=open(port, baud, rtsdtr); //在这里调用DLL里的函数label2.setText(”resolve ok…”);}else{label1.setText(”resolve failed…”);}}else{label2.setText(”load DLL failed…”);}label1.show();label2.show();return a.exec();}Qt调用DLL方法三:直接调用DLLVC的引用库文件为xxx.lib,GCC的为xxx.a,通过比较两种库文件的格式,发现很相似。

于是把xxx.dll,xxx.lib和xxx.h复制到Qt的project下,直接把xxx.lib改为xxx.a, 根据Qt的库名字的格式,在xxx.a的前面加上lib,即为libxxx.a。

再在Qt的.pro文件中最后面加上LIBS += -L. –lxxx //增加当前目录下的libxxx.a在Qt的源文件中加上#include “xxx.h”现在就可以直接调用xxx.h中的函数了。

// xxx.h#ifndef XXX_H#define XXX_HWINAPI int xxx_func(void);#endif// main.cpp#include “xxxh”#include#includeint main(int argc, char *argv[]){QApplication a(argc, argv);QLabel label1(”label-1″); //显示打印信息,将就着用了。

if(xxx_func()) //“xxx_func”为DLL包含的实际函数名,必须实际存在{label1.setText(”Run DLL success!…”);}label1.show();return a.exec();}总结:类似于调用DLL的交叉编程使用的场合很多,还可以用Qt生成DLL,给其它工具调用。

说到底,VC和Qt等本质上都是一样的,只是提供了不同的C++库。

相关主题