1、首先新建一个Win32控制台应用程序,然后选择dll==》勾选导出符号==》不勾选预编译头文件,删除stdafx.h stdafx.cpp targetver.h dllmain.cpp文件,然后build即可生成dll,另外在改变dll的生成路径可在设置界面改变General下面的Output Directory,改变lib的生成路径可在,Linker下面的Advanced中的Import Library修改,其中$(SolutionDir)表示解决方案目录,$(Platform)表示平台目录(x64或x86),$(Configuration)表示编译模式(Debug/Release),Dll库是函数的实现,Lib是函数的声明。

ps:这里介绍的是动态库DLl的创建,编译后会提供两个文件,一个引入库.lib(也称导入库文件)文件和一个DLL文件;还有一种是静态库.lib的创建,函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.EXE文件)。当发布产品时,只需要发布这个可执行文件,并不需要发布被使用的静态库。(所以有些项目导入三方库,不需要添加dll,是因为导入的是静态第三方库,不是动态第三方库,如果是动态,没有添加dll肯定会报错)

PS:虽然引入库的后缀名也是“lib”,但是,动态库的引入库文件和静态库文件有着本质的区别。对一个DLL文件来说,其引入库文件(.lib)包含该DLL导出的函数和变量的符号名,而.dll文件包含该DLL实际的函数和数据。在使用动态库的情况下,在编译链接可执行文件时,只需要链接该DLL的引入库文件,该DLL中的函数代码和数据并不可复制到可执行文件,直到可执行程序运行时,才去加载所需的DLL,将该DLL映射到进程的地址空间中,然后访问DLL中导出的函数。这时,在发布产品时,除了发布可执行文件以外,同时还需要发布该程序将要调用的动态链接库。

PS:综上所述,无论导入静态还是动态库,发布程序时都不需要添加lib文件,区别在于,用动态库的程序需要添加dll,但是程序比较小,用静态库的程序,程序会比较大,因为EXE把lib所有信息包进去了。

PS:静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接 库。静态链接库与静态链接库调用规则总体比较如下。

静态链接库运行之前就加载了,而且一直存在直到关闭程序,动态DLL实在运行时再加载,不用一直占内存,dll模块内部更改了,是要替换Dll即可,方便维护。优点明显,但是dll如果丢失或被误删,就无法运行了

2、如果是QT的库可以参考我上一篇博客。

下面介绍库的调用:一般有两种方法,一种是改变属性,一种是代码#paragram

2.1、先导入头文件,然后指定导入lib库,用#pragma comment(lib,".\xxxx.lib"),需要注意dll库需要放在exe生成的目录下面。

2.2、导入头文件,Linker下面常规添加lib的路径,Linker=>输入=>附加依赖项,加上lib文件名,同1一样,需要将dll库放在exe同级目录下。

上面导入头文件的方法也有两种,一种是直接添加到项目中,一种是放在一个include文件夹里面,然后在C/C++=>General=>Addtional Include Directories添加该路径,然后就可以#include xxx.h调用了。

//2021-4-28 补充

3、说明一下lib和dll的区别:你建了一个dll项目,编译完成后会生成一个lib和dll文件,简单的来理解就是,lib就是记录了头文件信息(函数名称和位置),dll记录了cpp中的内容,即lib主要用于链接,dll主要用于功能实现,所以一般项目导入lib后,编译时没有dll有lib,编译是可以通过的,但是如果程序运行起来,dll必须有,此时lib不需要。

PS:这里指的是动态库dll,不是静态库lib,需要注意。

4、很多人估计对静态链接库(Static Link Library)和动态链接库(Dynamic Link Library)有点云里雾里,看我来解释,前者对应显示链接,后者对应隐士链接(不要问我啥是显式,啥是隐式,百度去),我上面第二点介绍的就是静态链接方法,其特征就是比较麻烦,需要.h .lib 文件要很多步骤,而且还没到你代码是否执行到调用dll的位置时即程式调起来后,这个dll就必须存在,不然就会报错(这个是针对动态dll,如果是静态lib不会报错)。动态链接是啥意思呢,你编译或者用的时候,不需要其,lib和.h头文件,只需要dll文件,将其放入工程目录中,然后用win32 API LoadLibrary加载、GetProcAddress获取接口函数地址(就是函数指针,你要传啥就传给它就行了)、最后不用的时候记得释放用FreeLibrary内存,这个就比较好用,你啥时候用,啥时候导入。(这个针对是动态dll,静态lib无法动态链接,因为它没有dll

PS:这里指的是库的两种导入方式,静态链接和动态链接。

5、使用LoadLibrary动态链接dll时,如果参数里没有指定dll的完整路径,windows将遵循以下的顺序来定位dll:

5.1:EXE所在的目录。

5.2:工程目录。

5.3:Windows系统目录。

5.4:Windows目录。

5.5:环境变量中Path的一系列目录。

//2021-4-30 10:19:06 补充

6、这里解释一下./ ../ 和.\ ..\的区别,在终端敲过代码的都知道,.表示是当前路径  ..表示是上一级,在vs项目中属性中配置路径,为了让代码具有可移植性,最好都是用相对路径,方便后续的修改,在property里有头文件目录和lib目录设置,在这里,./和..\  ../和..\意思是一样的,./ .\处于当前项目代码所处的路径,因为这里不是代码,如果是在代码里,大家都知道,我们\表示的是转义字符,所以代码里想要表示\必须要用\\表示,总结一下:属性设置/ = \,代码中/ = \\,OK!

7、静态链接库(隐士链接),

7.1 lib文件的添加方法说明如下:

方法1: 通过设置工程配置来添加lib库.

A、添加工程的头文件目录:工程->属性->配置属性->c/c++->常规->附加包含目录:加上头文件存放目录。添加头文件参考2.2.1.2 
B、添加文件引用的lib静态库路径:工程->属性->配置属性->链接器->常规->附加库目录:加上lib文件存放目录。 
C 然后添加工程引用的lib文件名:工程->属性->配置属性->链接器->输入->附加依赖项:加上lib文件名。

这种方法比较繁琐,且不直观,而且还可能要争对debug版本和release版本作不同的配置,因为我们生成的两个版本的库可能放在不同的目录中的

方法2: 使用编译语句:

#ifdef _DEBUG
 #pragma comment(lib,"..\\debug\\LedCtrlBoard.lib")
 #else
 #pragma comment(lib,"..\\release\\LedCtrlBoard.lib")
 #endif


这种方法直观,方便,且可以按如上直接区分出Debug版本和Release版本的不同目录.当然,通过宏,还可以区分更多版本.但是在指定目录时,不小心容易出错.

7.2 头文件.h的添加方式:

在调用DLL中导出的函数之前要include对应的头文件,可以写绝对路径,也可以拷贝到工程调用源文件的同一目录下,也可以通过VS添加(include)头文件目录,VS中配置方法: 
(1)VS项目->右击属性->配置属性->VC++目录->包含目录 
(2)VS项目->右击属性->配置属性->C/C++->常规->附加包含目录

7.3添加DLL:

一般将dll拷贝到运行时目录即可,与调用者exe文件在同一目录,当然有其他方法添加环境变量PATH, 
(1)VS项目->右击属性->配置属性->VC++目录->可执行目录 
(2)设定DLL目录的位置,具体方法为:项目右击->属性 -> 配置属性 -> 调试 ->工作目录,在这里设置dll的路径就可以了

注1:release版本和debug版本的区分,每种版本的设置都是独立的,要分别设置 

上面仅仅对单个项目有效,我们配置过opencv库的都知道,有一种是全局配置lib和include头文件,对所有的项目有效,以Debug版为例,步骤如下: 
(1) 点击“视图”→“其他窗口”→“属性管理器” 
(2) 从左侧项目中打开“Debug| Win32”→“Microsoft.Cpp.Win32.user” 
(3) 双击“Microsoft.Cpp.Win32.user”,在弹出的窗口,点击左侧VC++目录,编辑右侧的可执行文件目录、包含目录与库目录,分别添加对应的路径 
(4) 附加依赖项,单击“链接器”→“输入”→“附加依赖项”,填入依赖项.lib后缀的文件名。