- 在windows下一般可以看到后缀为dll和后缀为lib的文件,但这两种文件可以分为三种库,分别是动态链接库(Dynamic-Link Libraries),目标库(Object Libraries)和导入库(Import Libraries),下面一一解释这三种库。
目标库(Object Libraries)
目标库又叫静态链接库,是扩展名为.LIB的文件,包括了用户程序要用到 的各种函数。它在用户程序进行链接时,“静态链接”到可执行程序文件当中。例如,在VC++中最常使用到的C运行时目标库文件就是LIBC.LIB。在链 接应用程序时常使用所谓“静态链接”的方法,即将各个目标文件(.obj)、运行时函数库(.lib)以及已编译的资源文件(.res)链接到一起,形成 一个可执行文件(.exe)。使用静态链接时,可执行文件需要使用的各种函数和资源都已包含到文件中。这样做的缺点是对于多个程序都使用的相同函数和资源 要重复链接到exe文件中,使程序变大、占用内存增加。
导入库(Import Libraries)
导入库是一种特殊形式的目标库文件形式。和目标库文件一样,导入库文件的扩展名也是.LIB,也是在用户程序被链接时,被“静态链接”到可执行文件当中。但是不同的是,导入库文件中并不包含有程序代码。相应的,它包含了相关的链接信息,帮助应用程序在可执行文件中建立起正确的对应于动态链接库的重定向表。比如KERNEL32.LIB、USER32.LIB和GDI32.LIB就是我们常用到的导入库,通过它们,我们就可以调用Windows提供的函数了。 如果我们在程序中使用到了Rectangle这个函数,GDI32.LIB就可以告诉链接器,这个函数在GDI32.DLL动态链接库文件中。这样,当用 户程序运行时,它就知道“动态链接”到GDI32.DLL模块中以使用这个函数。其实说白了导入库就是一个索引,一个dll动态链接库的索引表,这是我的 理解。
动态链接库(Dynamic-Link Libraries)
“动态链接”是将一些公用的函数或资源组织成动态链接库文件(.dll),当某个需要使用dll中的函数或资源的程序启动时(准确的说是初始化时),系统将该 dll映射到调用进程的虚拟地址空间、增加该dll的引用计数值,然后当实际使用到该dll时操作系统就将该dll载入内存;如果使用该dll的所有程序 都已结束,则系统将该库从内存中移除。使用同一dll的各个进程在运行时共享dll的代码,但是对于dll中的数据则各有一份拷贝(当然也有在dll中共享数据的方法)。 动态链接库中可以定义两种函数:输出函数和内部函数。输出函数可以被其他模块调用,内部函数只能被动态链接库本身调用。动态链接库也可以输出数据,但这些数据通常只被它自己的函数所使用。
- 静态链接库
- 先建立一个静态链接库项目,编写一个静态链接库,Tool.lib,我们需要的是头文件,和生成的.lib文件。
- 再建立一个工程去使用这个.lib文件。
- 拷贝生成的静态链接库的头文件和.lib文件到使用这个库的文件目录。
- 包含库文件的头文件。
#include "tool.h"
#pragma comment(lib,"tool.lib")
- 然后就可以直接使用静态链接库里面的函数了。
- 动态链接库(隐式链接)
- 建立一个动态链接库的工程,生成一个dll。
- 头文件加入如下代码,__declspec(dllexport) 声明导出,extern "C" 以C语言风格函数生成(注意C大写)不以C语言风格函数导出,会按照C++重载函数生成不同的函数名字,会找不到!
extern "C" __declspec(dllexport) int plus(int a,int b);
- 新建调用次动态链接库的工程。
- 把动态链接库生成的.lib文件拷贝到当前文件目录下面。
- 添加如下代码,即可直接调用plus函数。
//声明次函数是导入函数
extern "C" __declspec(dllimport) int plus(int a,int b);
#pragma comment(lib,"dll.lib")
- 动态链接库(显式调用)
- 只要把要使用的dll放入和目标exe同级目录下即可。
- 调用代码:
#include <stdio.h>
#include <windows.h>
typedef int (* FUNC)(int a,int b);
int main(int argc, char* argv[])
{
FUNC fPlus;
HINSTANCE hModule = LoadLibrary("dll.dll");
if(hModule == NULL)
{
printf("NULL hModule");
return 0;
}
fPlus = (FUNC)GetProcAddress(hModule,"plus");
printf("%d\n",fPlus(3,4));
return 0;
}
- 动态链接库-隐藏自己的dll函数名字Def导出
- 在dll项目中定义.def文件
EXPORTS //声明导出
函数名 函数序号 是否生成函数名字
plus @66 NONAME
- 学过PE导入表应该了解上述含义,函数序号就是函数在导入表里面的编号,NONAME 就是不生成函数名字,可以隐藏我们的重要函数名。
- 想学怎么调用,等学了PE导入表就可以啦。