C++中动态和静态库(dll) 使用(转)

发布时间 2023-05-20 19:00:36作者: xiangcunzhizi

目录:

1.lib 与 dll 介绍

2.动态库的生成与使用

3.静态库的生成与使用


 1.首先介绍下静态库(静态链接库,.lib文件),动态库*(动态链接库,.dll文件)的概念,两者都是代码共享的方式.

静态链接:静态链接是指在编译的时候就把模块的内容加载进来一起编译,这样编出来的exe文件包含了模块的内容,因此会比较大。

动态链接:程序在运行时去加载模块中所需要的函数,exe文件与模块文件是分离的。一般来说,静态链接用的是lib文件,动态链接用的是dll文件。

静态库:在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件,这种库称为静态库,其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝.即静态库中的指令都全部被直接包含在最终生成的EXE文件中了.

         在VS中新建生成静态库的工程,编译生成成功后,只产生一个.lib文件

动态库:动态链接库是一个包含可由多个程序同时使用的代码和数据的库,dll不是可执行文件。动态链接库提供了一种方法,使进程可以调用不属于其可执行代码的函数,函数的可执行代码位于一个dll中,该dll包含一个或多个已被编译,链接并 与使用他们的进程分开存储的函数。

         VS中生成动态库的工程,编译成功后,产生一个.lib文件和一个.dll文件

那么上述静态库和动态库中的lib有什么区别呢?

静态库中的lib:该LIB包含函数代码本身(即包括函数的索引,也包括实现),在编译时直接将代码加入程序当中

动态库中的lib:该LIB包含了函数所在的DLL文件和文件中函数位置的信息(索引),函数实现代码由运行时加载在进程空间中的DLL提供

总之,lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll

 2动态库的生成与使用

2.1生成动态库

以VS2019为例

 可以看到生成了一个dllmain.cpp 文件,这是dll应用程序的入口,注意它和普通工程的入口main函数不同,这个文件我们不需要修改。

 创建一个MyDll.h和MyDll.cpp,MyDll.h文件如下:

 1 #ifndef MYDLL_H
 2 #define MYDLL_H
 3 
 4 //新建生成dll的工程时,vs默认定义了宏MYDLL_EXPORT,因此,MYDLL_API 是 __declspec(dllexport),用来导出
 5 //当我们在静态调用dll时,我们包含该头文件,由于没有定义MYDLL_EXPORT,所以DLL_API是 __declspec(dllimport),用来导入
 6 //如下示例展示常用的场景:调用接口函数,不涉及接口类
 7 #ifdef MYDLL_EXPORTS
 8 #define MYDLL_API extern "C" __declspec(dllexport)
 9 #else
10 #define MYDLL_API extern "C" __declspec(dllimport)
11 #endif // MYDLL_EXPORTS
12 
13 MYDLL_API int Add(int x, int y);
14 
15 MYDLL_API void maopao(int* p, int count);

MyDll.cpp文件如下:

 1 #include "pch.h"
 2 #include "MyDll.h"
 3 #include<iostream>
 4 using namespace std;
 5 
 6 MYDLL_API int Add(int x, int y)
 7 {
 8     return x + y;
 9 }
10 
11 //冒泡算法
12 MYDLL_API void maopao(int* p, int count)
13 {
14     for (int i = 0; i < count - 1; i++) //进行n-1轮排序
15     {
16         for (int j = 0; j < count - i - 1; j++)
17         {
18             if (p[j] > p[j + 1])
19                 swap(p[j], p[j + 1]);
20         }
21     }
22 
23 }

点击build,在Debug目录下生成.dll 和.lib文件

2.2调用动态库

调用dll有两种链接方式:隐式链接和显式链接,无论哪种方式都要求将dll放在程序文件目录下。

方法1:隐式链接

隐式链接 需要.h文件,dll文件,lib文件

添加.h文件 :直接添加在程序文件目录下,直接引用

添加.lib文件(两种方法) :

          1)属性页->链接器->常规->附加库目录( 添加.lib文件路径);属性页->链接器->输入->附加依赖项 (添加.lib文件名)

 

     

           2)直接用#pragma comment(lib,"MyDll.lib) (需要将该lib文件放到与程序工作目录下)

          

 配置好文件后编写代码

 1 #include <iostream>
 2 #include"MyDll.h"
 3 using namespace std;
 4 
 5 #pragma comment(lib,"MyDll.lib")
 6 int main()
 7 {
 8     std::cout << "Hello World!\n";
 9     cout<< Add(3, 4)<<endl;
10 
11 }

方法2:显式链接

显式链接直接调用WIN32 API函数LoadLibraryGetProcAddressFreeLibrary显式地装载、卸载dll。

主要思路:

1)声明头文件<windows.h>,说明我想用windows32方法来加载和卸载DLL
2)然后用typedef定义一个指针函数类型(这个指针类型,要和你调用的函数类型和参数保持一致)
3)定义一个句柄实例,用来取DLL的实例地址。(HMODULE hdll;)
4)加载目标DLL,即 LoadLibrary()函数,将DLL加载到句柄实例,若成功则返回该DLL模块的句柄,否则返回NULL
5)获得导出函数的地址,即GetProcAddress()函数,成功时返回函数地址,否则返回NULL
6)调用导出函数
7)卸载dll

 1 #include <iostream>
 2 #include<Windows.h>
 3 using namespace std;
 4 
 5 typedef int(*add_dll)(int a, int b);//定义一个指向dll中的函数的指针函数类型
 6 int main()
 7 {
 8     HMODULE hdll = LoadLibrary(L"MyDll.dll");//获取dll地址
 9     if (hdll != NULL)
10     {
11         add_dll myadd = (add_dll)GetProcAddress(hdll, "Add");///获取dll中的函数地址
12         if (!myadd)
13         {
14             cout << "load fun error\n" << endl;
15             return -2;
16         }
17         cout << myadd(3, 4) << endl;
18     }
19     else {
20         cout << "load dll error\n" << endl;
21         return -1;
22     }
23     FreeLibrary(hdll);//卸载dll
24     return 0;
25 }

3.生成静态库

3.1.创建静态库

生成一个空项目,添加.h文件和.cpp文件.项目属性中做如下配置,生成静态库。

.h文件

1 #ifndef  STACTICLIB_H
2 #define  STACTICLIB_H
3 
4 int Plus(int x, int y);
5 
6 #endif //  STACTICLIB_H

.cpp文件

1 #include "StaticLib.h"
2 
3 int Plus(int x, int y)
4 {
5     return  x+y;
6 }

 

编译工程后就会生成一个.lib文件 

3.2 使用静态库

把.lib和.h都放到需要使用的项目目录下。然后编写下面代码,即可实现对静态库中函数的调用

1 #include <iostream>
2 #include"StaticLib.h"
3 #pragma comment(lib,"staticlib.lib")
4 
5 int main()
6 {
7     std::cout << Plus(7, 8) << std::endl;
8     std::cout << "Hello World!\n";
9 }

当然,对于#pragma comment(lib,“StaticLib.lib”)这句话也可以不加,这需要在项目属性设置中添加附加依赖项。参考动态库中隐式链接中的相关步骤。


 

转自https://www.cnblogs.com/TenosDoIt/p/3203137.html

参考https://blog.csdn.net/u013610563/article/details/124485124