Qt是跨平台工具,显然能和windows的动态库一起使用。
在Windows操作系统上,库以文件的形式存在,并且可以分为动态链接库(DLL) 和静态链接库两种。动态链接库文控以.dll为后缀名,静态链接库文控以.lib为后缀名。不管是动态链接库还是静态链接库,都是向它们的调用者提供变量、函数或举。
实质上,windows系统库主要以dll动态库为主,所以会在C:\Windows\System32下有大量的dll结尾的库文件。
⚠️windows下理论概念比较多适合萌新消化,大佬绕行!
一、简述动态链接库
动态链接库的源码就是函数或类的具体实现,源码经过编译后会生成一个后缀名为dll的文件,这个文件就是动态链接库文件,是一个二进制形式的文件,不可以单独运行,必须和它的调用者一起运行。它通常可以向其调用者提供变量、函数或类。
1、调用者(或称为使用者) 可以是应用程序 (exe程序) 或其他动态链接库;
2、提供给调用者调用的函数通常被称为导出函数;
3、提供给调用者使用的类通常被称为导出类。
动态链接库经过编译后会生成一个.lib文控和一个.dll文件,这里的.lib文件不是指静态链接库文件,而是导入库文文件,虽然后缀名和静态链接库文控相同,但是两者没有任何关系。
从调用来分,又有以下两种区别:
隐式链接:在程序执行的时候,就将DLL文件加载到应用程序中;
显式链接:应用程序在执行过程中随时可以添加DLL文件,也可以随时卸载DLL文件,这是隐式链接无法做到的,所以显示链接具有更好的灵活性,对于解释性言语更为合适。
.lib导入库文件中存放的是DLL文控中导出函数的名称和地址,应用程序采用隐式链接动态链接库时,会把导入库文控中的内容(导出函数或类的名称和地址) 复制到应用程序的代码中,当应用程序运行时,就能知道动态链接库中导出函数(或类) 的地址了。
二、动态链接库dll的分类
简单的说把DLL分为非MFC DLL(又称Win 32 DLL)和MFC DLL。
非MFC DLL (Non-MFC DLL) 也称Win32 DLL,它指的是不用MFC的类库结构直接用C或者C++编写的DLL,其导出的函数是标准的C或者c++接口,能被非MFC或MFC编写的应用程序所调用。如果建立的DLL不需要使用MFC,那么应该建立Non-MFC DLL,因为使用MFC会增大用户库的大小,会浪费用户的磁盘和内存空间。
MFC DLL意味着可以在这种DLL的内部使用了微软的MFC库,这种情况不属于本文讨论范围之内;
三、动态链接库dll开发和调用
一个有用的DLL,首先要把DLL中的变量、函数或类导出,再编译生成dll文件。导出就是对那些要给外部程序使用的变量、函数或类进行声明。
通常有两种导出方式:
第一种方式是通过关键字 declspec(dllexport)导出;
另一种是采用模块定义文件.def导入文件(大部分情况下用的少不做演示);
无论采用哪种方法编译,最终都会生成dll文件和lib文件 (导入库文件)。
3.1 通过关键字 declspec(dllexport)导出
使用关键字 declspec(dllexport)可以从DLL导出数据、函数、类或类成员函数。这种方式比较简单,只要导出的内容前加 declspec(dllexport)即可。以下vs中演示第一种:
(1)、vs新建,动态链接库DLL;
(2)、项目名称,勾选将解决方案和项目放在同一目录;
(3)、默认会打开dllmain.cpp,直接关闭就行;
(4)、项目,鼠标右键,添加,类;
(5)、输入类名;
(5)、AddDll.h和AddDll.cpp分别如下;
注意:其类型声明前面加上“__declspec (dllexport)”,为什么这里没有用到类,实测QLibrary调用的win32 dll必须是c语言,如果是C++必用qt自身创建dll。
(6)、一般情况下最终都是需要Release版本都,我这里改Debug为Release,然后生成;
(7)、在项目Release目录下,找到我们需要动态链接库dll文件和lib文件 (导入库文件)
3.2通过Qt调用dll
Qt调用DLL的导出函数有4种方法:
第一种是使用Win32 API:
第二种是使用Qt自身的API:
第三种是直接调用DLL:
第四种是Qt Creator可视化调用法,点点鼠标即可。
(1)、使用win32api
这种方法主要使用win32的api函数LoadLibrary(), 这种方法已经使用较少了,有兴趣的可参考下文;
(4条消息) 3.利用Win32 API调用DLL_api调用dll方法_深山里的小白羊的博客-CSDN博客https://blog.csdn.net/qq_33757398/article/details/81564522
(2)、使用Qt自身的API函数QLibrary类
该方法是比较常用的一种,以下演示一下:
需要注意的是QLibrary:: resolve函数中,明确说明,该符号必须作为 C 函数从库中导出。
#include "mainwindow.h"
#include <QApplication>
#include <QLibrary>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QLibrary lib;
QString str1 = QApplication::applicationDirPath();
qDebug()<<"str1="<<str1;
QString str(str1+"/DllTest.dll" );
lib.setFileName(str);
if(lib.load())
{
typedef int(*AddFunction)(int a,int b);
AddFunction Add = reinterpret_cast<AddFunction>(lib.resolve("MyAdd"));
if(!Add)
{
qDebug()<<"resolve failed="<<lib.errorString();
}
else
{
int out=Add(1,3);
qDebug()<<"out="<<out;
}
}
else
{
qDebug()<<"load failed!";
}
MainWindow w;
w.show();
return a.exec();
}
(3)、直接调用dll
这种情况下,最省事,但是它需要3个文件,一个lib,一个dll,还需要一个.h文件(源dll)
①将lib拷贝到qt的.pro目录下,如图所示;
②将dll复制到生成exe的坐在目录下;
③在qt的.pro文件中引用.lib,引用方式如下,-l你的lib文件名;
LIBS+=-L$$PWD/./ -lDllTest
前面表示绝对路径下的当前目录,仅需要修改后面lib名就行,比如你的lib是test123.lib,尾部应该是-ltest123,改完pro文件,记得按ctrl r让qt重新加载;
④添加源dll的头文件,原则上建议,新建一个与.lib同名的.h,这样可以防止编码等问题,如下图先项目右键,添加新文件,然后是C/C++ Header File,输入lib名字,最后将源dll里的头文件函数复制过来并且删除__declspec(dllexport);
⑤包含上一步新建的头文件,直接调用函数即可;
(4)、Qt Creator可视化调用法
这种方法与上面第三种类似,也是需要.dll和.lib、新建.h头文件,但是这种优势是,qt会自动解决.pro文件的修改。
可先进行这三步①②④,内容都是同第三种方法,把dll和.lib复制到对应位置,新建一个与.lib同名的.h文件并填充内容。
③这步稍微有些不同,如下图,项目右键,添加库,外部库,选择.lib路径后,qt自动解决引用和路径,这在目前看起来好像优势不大,但当你库文件多而杂时,它事半功倍。
⑤这一步其实也一样,包含头文件,直接调用即可;
本文重点还是讨论qt调用vc生成的dll,至于vc之间互相调用更加灵活,可参考以下文章
(4条消息) 在Qt和VS中使用动态链接库.dll文件----以隐式链接的方式_qt vs dll_咖啡与乌龙的博客-CSDN博客https://blog.csdn.net/qq_40459977/article/details/125652187 原创不易,如有帮助,请多多关注,持续输出更多qt6相关内容!