动态链接库

静态链接库的缺陷

  • 链接时将函数加入到exe导致exe变大
  • 在运行时对于不同进程他们所使用的同一个函数都会独占空间,造成资源浪费

怎么解决

 利用之前学习过的内存知识,例如映射类型的内存块
 将这些公共代码放在文件中没在进程运行的时候在加载该文件
 并且在内存中只需要加载一边,不同进程使用同一份公共代码时,只需要将之前加载过的这个文件映射到自己内存中即可

什么是动态链接库

动态链接库(dynamic link library 缩写位 dll),是微软公司在windows操作系统中
实现共享函数库概念的一种方式

这些库函数的扩展是 .dll .ocx(包含activeX控制的库)

创建动态链接库

  1. extern "C" _declspec(dllexport) 返回类型 调用约定 函数名 (参数列表)
  2. 使用.def文件
    制定导出函数,并告知编译器不要以修饰后的函数名作为导出函数名,而以指定的函数名导出函数
EXPORTS
函数名   @编号
函数名   @编号    NONAME

使用序号导出的好处:

名字是一段程序最精华的注释,通过名字可以直接猜到函数的功能

通过使用序号,可以达到隐藏的目的

如何调用动态链接库(显式调用)

  1. 定义函数指针
  2. 声明函数变量
  3. 通过LoadLibrary() 动态加载DLL到内存中
  4. 通过GetProcAddress()获取函数地址
  5. 调用函数
  6. FreeLibrary()释放动态链接库

exp:

// 定义
// MyFunction.h
//根据名字查找进程id
//extern "C" _declspec(dllexport) 返回类型 调用约定 函数名 (参数列表)
extern "C" _declspec(dllexport) DWORD _stdcall find_processid_by_name(PWCHAR process_name);
// MyFunction.cpp
#include "stdafx.h"
#include
#include
DWORD find_processid_by_name(PWCHAR process_name)
{
    HANDLE hand = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if ((int)hand == -1)
    {
        return GetLastError();
    }
    PROCESSENTRY32 process_info = { 0 };
    process_info.dwSize = sizeof PROCESSENTRY32;
    if (!Process32First(hand, &process_info))
    {
        return GetLastError();
    }
    do
    {
        if (!wcscmp(process_info.szExeFile, process_name))
        {
            return process_info.th32ProcessID;
        }
    } while (Process32Next(hand,&process_info));
    return 0;
}
//调用
//Main.cpp
#include "stdafx.h"
#include "windows.h"
//显示的导入
//1 定义函数指针
typedef DWORD(_cdecl * PFindProcessW)(PWCHAR);
//2 定义变量
PFindProcessW pMyFindProcessW = NULL;
int main()
{
    //3 装载DLL
    HMODULE hModule = LoadLibrary(L"动态链接库.dll");
    //4 获得函数
    pMyFindProcessW = (PFindProcessW)GetProcAddress(hModule, "find_processid_by_name");
    DWORD err = GetLastError();
    WCHAR name[] = L"notepad.exe";
    printf_s("PID=%d \r\n", pMyFindProcessW(name));
    getchar();
    return 0;
}

DLL和EXE的区别

  • 动态链接库DLL与可执行文件exe本质上没有区别,我们统称为模块
  • 他们内部的数据组织结构都遵循一个叫做PE文件格式的格式
  • 两者都可以对外提供函数,只不过DLL提供的更多