磁盘
磁盘相关的 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
文件中