磁盘
磁盘相关的 API 函数:
GetLogicalDriveStrings:获取所有的逻辑盘符
GetDriveType:获取类型
GetDiskFreeSpace:获取磁盘空间的信息
1 |
|
动态链接库
创建一个动态链接库文件:

创建完 DLL 工程后会出现一个 DllMain 函数,它与传统的 main 或 WinMain 函数不同,因为 dll 文件不像 exe 文件一样直接运行,它是提供函数给其他程序使用的,不需要入口这样的概念,所以 dll 文件被执行的第一行代码并非是 DllMain
当程序被创建、程序中有线程被创建、程序即将退出、程序中有线程将要退出时会调用 DllMain 函数
导出 dll 的方式:
声明导出:
在
.h文件中进行声明1
2
extern "C" _declspec(dllexport) int Add(int a, int b);在
.cpp中实现1
2
3
4
5
6
7
extern "C" int Add(int a, int b) {
return a + b;
}
int Sub(int a, int b) {
return a - b;
}编译成功后,就可看到
dll文件
使用 PEiD v0.95 查看
dll文件的导出表,其中存储了dll文件的导出函数Add,只有函数导出了才能给其他模块使用
def文件导出:.cpp中实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
int Fun(){
printf("Hello world");
return 0;
}
int Fun2(){
printf("Hello 15pb");
return 0;
}
int Fun1(){
printf("你好 十五派");
return 0;
}先制作一个
def脚本文件
然后设置工程属性:

最后编译,使用 PEiD v0.95 查看,导出成功

使用 dll 文件的方式:
隐式链接
添加一个空项目,包含头文件,载入
lib文件,调用函数1
2
3
4
5
6
7
8
9
10
11
12
13//1 包含头文件
//#include "C:\\Users\\SouLinker\\source\\repos\\TestDll_36\\Dll1\\Dll1.h"
//2 载入lib文件
int main()
{
int nNum1 = 10;
int nNum2 = 5;
int nSum = Add(nNum1, nNum2);//只能使用导出了的函数
//int nSub = Sub(nNum1, nNum2);
return 0;
}
显示链接:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef int(*ADD)(int a, int b);
ADD g_pFunAdd = NULL;
int main()
{
int nNum1 = 10;
int nNum2 = 5;
//1载入dll
HMODULE hModule = LoadLibrary(_T("Dll1.dll"));
//2根据函数名得到函数地址
g_pFunAdd = (ADD)GetProcAddress(hModule, "Add");
//3调用函数
int nRe = g_pFunAdd(nNum1, nNum2);
//4释放
FreeLibrary(hModule);
return 0;
}
隐式链接会暴露 dll 的调用信息:

显示链接不会暴露此信息:

探讨动态链接库和静态链接库
dll 是动态链接库:代码和数据都不会放在 exe 中,而是在程序运行时加载,缺点就是发布程序必须一起发布,否则无 dll 程序就无法运行
动态链接库增强了模块性,使用 dll 不需要关注功能怎么实现,只需包含头文件,将 dll 放到 exe 所在目录下,就可使用其中的函数;使用动态链接库更新软件更加方便,将程序分为多个部分,更新时也许只需更新其中几个 dll 即可,或更新 exe 也行,只要接口不变;windows 通过这种机制取节约内存
动态链接库的缺点:若某一个 dll 丢失或损坏,程序就运行不起来
若希望只发布 exe 程序就能使用,可以使用静态链接库

其他的声明导出,隐式链接和动态链接库的使用是一样的
编译动态链接库时,生成一个 dll 文件和一个 lib 文件,其中 lib 文件称为导入库,不包含代码和数据,只包含一些链接信息,链接器用它来解析代码中的函数调用
编译静态链接库时,会生成一个 lib 文件,称为对象库,包含代码和数据,在运行链接器时被添加到程序的 .exe 文件中