动态链接库(dynamic link library)介绍

代码放到exe中,肯定会造成磁盘冗余; 电脑ABCD四个软件,lib加入到代码中不是在编译期进入的,而是在运行期 (A进程启动,把dll加入到A进程中……),编译的时候不需要这份代码, 后缀是.dll

如果要更新软件,把dll换掉就可以了,所有软件都会跟着更新

 

分析DLL的工具

.dll中凡是能给外面用的函数叫 导出函数;

这个工具能看导出函数;

调win api的时候跟不到源码中,因为放到了dll中了

 

 

动态库的创建

 

文件导入并去掉宏,宏在静态库和动态库表现不一致

 

直接编译,生成dll文件,dll文件用工具打开, 然而并没有导出函数显示

 

导出函数

编译之后,用工具打开发现 默认的没有导出函数, 需要手动指定后,才导出;

就像类一样,默认时私有的;

用编译器命令导出

 

注意细节1:

两个cpp文件中把头文件注释掉了,编译之后,在工具中发现没有导出函数,为什么?

.h在预处理时期,预编译时把头文件中东西拷贝到.cpp文件中,没有包含头文件就没有导出函数了

 

注意细节2:

再把头文件加上,有了导出函数之后,编译之后生成了lib; 这里和静态的lib有区别,这里文件大小2kb;

这里只是一个描述性的lib,里面没有代码,这里描述dll中有哪些导出函数,是给开发者使用的

 

 

使用dll

使用dll, 头文件的这里改成dllimport, 告诉编译器这里用的是dll中的函数;

编译有误,找不到函数是在哪个dll文件中;

 

 

问题: 一个.cpp 两个.h声明,通过这些能判断这两个函数要加载哪个dll吗?

此时就用到了描述性的lib文件,拷到目录下(类似Makefile)

和静态的lib用法相同

编译的时候不需要dll,运行的时候需要;这里是运行状态; dll拿出来放到Debug文件里

 

1-导出全局变量

全局变量可以导出

VS的bug: dll中的全局变量,在VS的监视窗口中看不到值

 

 

2-导出类

类可以导出

但这样写不能导出,报错内容如下:

这样写就可以了

工具输出的内容,上面两个是构造还是有重载,下面那个是自己写的类

 

这个时候断点跟源码,能跟到自己写的库里,因为调试信息都放到.pdb文件里了;把这个删了就跟不进去了;

 

 

导出和导出函数的宏处理

这个东西,每次要用都要改,文件多了就很麻烦,用宏给它安排下

源码中 : 把宏的开关放到这里,全局的宏放置的位置

 

 

 

 

工具里导出的都是C++的符号,如果C的呢?

 

 

 

隐式/显示加载方式

隐式加载方式:

lib + .h (函数 全局变量 类 都可以用)

 

显示加载方式:

Ollydebug中强大的是插件,很多的dll,使用某个功能的时候,就会去加载dll

Ollydebug发布的时候,有没有用人家写的插件dll的lib和.h?没有啊, 所以它的加载方式和这里隐式加载方式不同,Ollydebug是显示的加载方式;

并不知道别人写的插件叫啥名字,是怎么加载别人写的dll呢?

做法: 当前路径下的某个文件夹,遍历文件夹下后缀为.dll的文件,加载到进程; 这时候的加载,只要有个文件名和文件路径就可以加载,显示加载 (函数 全局变量 类(很麻烦))

 

 

使用dll,调用导出函数的方法(Ollydebug加载dll的做法)

加载dll(加载到进程内存中) -> 获取导出函数的地址 -> 然后调用(通过函数地址的方式调用)-> 从进程中卸掉dll

01加载dll的api

参数: 的module指的是 dll / exe(主模块) 的地址 ;

返回值: 模块句柄和HINSTANCE两个是等价的;

HINSTANCE是可执行文件exe在内存中的首地址

HMODULE是dll在内存中的首地址

作用: 把dll加载到进程内存中

code:

注意细节:

调用多个 loadLibrary, 不会调用多个dll,而是句柄引用计数的值会增加;

调用两个loadLibrary,也要有两个FreeLibrary才能卸载掉;

02获取函数地址

模块句柄还有函数名填进去,返回的就是函数地址;

code: 用的函数指针接收

注意全局变量:

如果要拿全局变量怎么访问? 这里拿到的是地址

全局变量这样访问,指针p保存的是地址 *p访问值

 

 

调用: 普通调用就行

一步一步调试看现象

03从进程中卸掉dll

code:

 

code

#include <iostream>
#include <windows.h>

using PFN_ADD = int(*)(int, int);

int main()
{
    HMODULE hDll = LoadLibrary(R"(C:UsersYunaDesktopCR2windowswin01UseDllDebugdll.dll)");
    if (NULL == hDll)
    { 
        std::cout << "加载失败" << std::endl;
        return 0; 
    }

    PFN_ADD pfnAdd = (PFN_ADD)GetProcAddress(hDll,"Add");
    if (NULL == pfnAdd)
    {
        std::cout << "获取函数地址失败" << std::endl;
        return 0;
    }

    int nRet = pfnAdd(1,4);
    int i = 0;  //为了调试上一句
    FreeLibrary(hDll);
} 
内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/awmking/p/17019311.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!