静态链接库与动态链接库的建立与使用

说明

看滴水的视频写学习笔记总结

语言:c/c++

编译环境:vc++6.0

动态链接库方便我们封装函数,写大型项目的时候很重要,降低耦合,达到模块化的设计,方便重复使用与更新。

一、静态链接库

1.建立

新建一个静态链接库的项目,选好后,后面的全部点确定即可。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r7qXVliB-1589565371155)(E:\Typora\image\image-20200513230145384.png)]

再新建一个类。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uSeVI97C-1589565371160)(E:\Typora\image\image-20200513230527400.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uoMiBGY1-1589565371161)(E:\Typora\image\image-20200513230911215.png)]

然后在添加自己的函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1BJslIZp-1589565371165)(E:\Typora\image\image-20200513231202160.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-47g7ggXd-1589565371168)(E:\Typora\image\image-20200513231400781.png)]

然后按f7编译即可,在debug文件夹里生成.lib文件。

2.使用

(1).方式一

将先前生成的xxx.h文件和xxx.lib文件一并拖入我们要是用的项目文件中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jlseKshO-1589565371169)(E:\Typora\image\image-20200513231816763.png)]

在需要使用的项目中包含.h文件:#include”xxx.h”

在需要使用的项目中包含.lib文件:#pragma comment(lib,”xxx.lib”)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yY6A9nWz-1589565371170)(E:\Typora\image\image-20200513233120656.png)]

注意.cpp文件生成的.lib文件要同样的.cpp文件才能引用,.c文件无法引用

(2).方式二

将 xxx.h 和 xxx.lib 复制到要使用的项目中

在要使用的项目中包含:#include”xxx.h”

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wFI2nQTe-1589565371171)(E:\Typora\image\image-20200513233815739.png)]

3汇编层,lib的调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8H81UvfB-1589565371172)(E:\Typora\image\image-20200513235213767.png)]

虽然我们这里没用写Plus的,但是可以步入查看这个函数的。

按f11步入。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4rMsiYa0-1589565371173)(E:\Typora\image\image-20200513235349067.png)]

就像我们的printf,也是一个函数,只不过是由C语言自身封装的,也可以步入函数查看。

3.静态链接库的特点

用OD打开刚才调用静态链接库的exe程序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eAfpNqWC-1589565371174)(E:\Typora\image\image-20200513235938502.png)]

换句话说,使用静态链接库生成的exe文件,可以不必和lib文件在同一文件夹

  1. 静态链接库里的代码实际上在程序调用后,编译是就嵌入了该程序。
  2. 使用静态链接生成的可执行文件体积较大,造成浪费
  3. 我们常用的printf、memcpy、strcpy等这些函数就来自这种静态库

二、动态链接库

1.建立

新建一个动态链接库的项目。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ky0B8cO0-1589565371174)(E:\Typora\image\image-20200514230738407.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nA47QcaI-1589565371175)(E:\Typora\image\image-20200514231449247.png)]

之后,我选A simple DLL project (只加一个入口的动态链接库)

然后新建一个类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pD6KkqC-1589565371176)(E:\Typora\image\image-20200514232159288.png)]

建立之后,即可在新建的xxx.cpp中添加代码。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9uP7VN1V-1589565371177)(E:\Typora\image\image-20200514232800409.png)]

在xxx.h中声明添加的函数,这一点有差别

extern “C” -declspec(dllexport) int Plus (int x , int y)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FZV7S1mK-1589565371179)(E:\Typora\image\image-20200514233351832.png)]

名称意义
extern表示这是个全局函数,可以供各个其他的函数调用;
“C”按照C语言的方式进行编译、链接
__declspec(dllexport)告诉编译器此函数为导出函数;

然后按f7编译,即可在debug文件夹中生成xxx.dll文件和xxx.lib文件

2.使用

我们生成的动态链接库,xxx.dll文件里装的是代码,而xxx.lib里面装是代码在哪个位置。

(1).方式一:隐身链接

  • 步骤1:将 xxx.dll文件和xxx.lib放到工程目录下面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fpwe3wFo-1589565371180)(E:\Typora\image\image-20200515235610607.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vXHIV5le-1589565371181)(E:\Typora\image\image-20200515235542912.png)]

  • 步骤2:将 #pragma comment(lib,“DLL名.lib”) 添加到调用文件

  • 步骤3:加入函数的声明

    extern “C” __declspec(dllimport) __stdcall int Plus (int x,int y);

名称意义
__declspec(dllimport)告诉编译器此函数为导入函数;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N9myggOZ-1589565371182)(E:\Typora\image\image-20200515234741434.png)]

完成上述三个步骤即可成功调用动态链接库

(2).方式二:显示链接

  • 步骤1:定义函数指针 , 即定义一种指向函数的指针

    typedef int ( *lpPlus )(int , int );
    typedef int ( *lpSub )(int , int );
    typedef int ( *lpMul )(int , int );
    typedef int ( *lpDiv )(int , int );
    
  • 步骤2: 声明指针变量

    lpPlus myPlus;
    lpSub mySub;
    lpMul myMul;
    lpDiv myDiv;
    
  • 步骤3: 动态加载dll到内存中,将动态链接库加载到当前空间。

    HINSTANCE hModule = LoadLibrary("xxx.dll")
    //HINSTANCE是指句柄,代表程序载入的模块,载win32下和HMODULE相同
    
  • 步骤4: 调用API函数获取动态链接库里的函数地址

    //函数名原来是什么,引号里就写什么,因为我们导出函数后别人根据函数名寻找。
    myPlus = (lpPlus)GetProcAddress(hModule , "Plus");
    mySbu = (lpSub)GetProcAddress(hModule , "Sub");
    myMul = (lpMul)GetProcAddress(hModule , "Mul");
    myDiv = (lpDiv)GetProcAddress(hModule , "Div");
    
  • 步骤5: 通过函数指针调用函数

    int a = myPlus(10,2);
    

具体流程如下图,跟着标号1、2、3、4、5、6。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pUfivFhZ-1589565371183)(E:\Typora\image\image-20200516004228211.png)]

完成显示链接。

特别说明,对应的句柄

Handle 是代表系统的内核对象,如文件句柄,线程句柄,进程句柄

HINSTANCE 在win32下与HMODULE是相同的东一

HWND 是窗口句柄

以上的都是一个无符号整形数据

(3).动态链接库的特点

我们还是用OD打开刚才调用动态链接库的exe程序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3m9CV5SJ-1589565371184)(E:\Typora\image\image-20200515235750650.png)]

再查看我们代码的反汇编地址,下断点,进入到调用库的函数的地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0aeoyOg5-1589565371185)(E:\Typora\image\image-20200516000136354.png)]

也就是说,我们只需更改动态链接库里的函数内容,即可对调用这个库的程序进行更改,而不用更新整个程序

所以动态链接库才是方便更改,且空间小。

真正实现模块化。

实现高类聚低耦合。

三、使用.def文件导出动态链接库

​ 通过使用.def文件导出动态链接库,可以选择性的隐藏动态链接库里的函数的名字,起到隐藏名字的作用,防止别人通过获取函数名而获取信息。

建立过程

开始和动态链接库的建立方式一样,新建一个类,名字为“TestDll”

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKiEEd0G-1589565371186)(E:\Typora\image\image-20200516013150551.png)]

声明函数就是直接声明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KReWr3tk-1589565371186)(E:\Typora\image\image-20200516013431627.png)]

  • 不同点是:新建一个文本文件,取名xxx.def

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H6CGwMO0-1589565371187)(E:\Typora\image\image-20200516013607802.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OVpf8T8c-1589565371188)(E:\Typora\image\image-20200516013956989.png)]

EXPORTS	
	
Plus   	@12
Sub	@15 NONAME
Mul    	@13
Div    	@16

然后按f7即可编译生成.dll文件。

查看该dll文件

我们用vc++6.0的工具DEPENDS打开刚才生成的dll查看他内部函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YumnIP78-1589565371188)(E:\Typora\image\image-20200516014252501.png)]

打开后

在这里插入图片描述

调用该dll文件

直接写函数名字

虽然函数名被隐藏了,但不管事隐式链接还是显示链接,都可以像原来一样直接通过写函数名字调用

通过写函数序号

不管有没有被隐藏函数名,都可以在显示链接时通过写函数序号调用该函数,不过记得将数字强转为char*类型

成的dll查看他内部函数

[外链图片转存中...(img-YumnIP78-1589565371188)]

——————————————————————
欢迎大家留言评论交流^ _ ^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值