目录:
1.lib 与 dll 介绍
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.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函数LoadLibrary
、GetProcAddress
和FreeLibrary
显式地装载、卸载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.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
标签:文件,lib,静态,C++,dll,int,链接 From: https://www.cnblogs.com/rocky-chen/p/17379864.html