动态链接库(网络编程相关名词)编辑
目录
1概述编辑
动态链接库文件,是一种
不可执行的
二进制
程序文件,它允许程序共享执行特殊任务所必需的
代码和其他资源。Windows 提供的DLL文件中包含了允许基于 Windows 的
程序在 Windows 环境下操作的许多函数和资源。一般被存放在 "C:\Windows\System32" 目录下。
Windows 中,DLL 多数
情况下是带有 ".dll" 扩展名的文件,但也可能是 ".ocx"或其他扩展名;
Debian系统中常常是 ".so" 的文件。它们向运行于 Windows
操作系统下的
程序提供
代码、数据或函数。
程序可根据 DLL 文件中的指令打开、启用、查询、禁用和关闭
驱动程序。
2优点编辑
-
扩展了 应用程序的特性;
-
可以用许多种 编程语言来编写;
-
简化了 软件项目的管理;
-
有助于节省 内存;
-
有助于 资源共享;
-
有助于应用程序的本地化;
-
有助于解决 平台差异;
-
可以用于一些特殊的目的。Windows 使得某些特性只能为 DLL 所用。
3依赖项编辑
当某个
程序或 DLL 使用其他 DLL 中的 DLL 函数时,就会创建依赖项。因此,该
程序就不再是独立的,并且如果该依赖项被损坏,该程序就可能遇到问题。例如,如果发生下列操作之一,则该
程序可能无法运行:
-
依赖 DLL 升级到新版本。
-
修复了依赖 DLL。
-
依赖 DLL 被其早期版本覆盖。
-
从 计算机中删除了依赖 DLL。
4入口点编辑
在创建 DLL 时,可以有选择地指定入口点函数。当进程或
线程将它们自身附加到 DLL 或者将它们自身从 DLL 分离时,将调用入口点函数。您可以使用入口点函数根据 DLL 的需要来初始化
数据结构或者销毁数据结构。此外,如果
应用程序是
多线程的,则可以在入口点函数中使用线程本地
存储(TLS) 来分配各个线程专用的
内存。下面的
代码是一个 DLL 入口点函数的示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
BOOL
APIENTRY DllMain(
HANDLE
hModule,
// DLL模块的句柄
DWORD
ul_reason_for_call,
// 调用本函数的原因
LPVOID
lpReserved
// 保留
) {
switch
(ul_reason_for_call)
{
case
DLL_PROCESS_ATTACH:
//进程正在加载本DLL
break
;
case
DLL_THREAD_ATTACH:
//一个线程被创建
break
;
case
DLL_THREAD_DETACH:
//一个线程正常退出
break
;
case
DLL_PROCESS_DETACH:
//进程正在卸载本DLL
break
;
}
return
TRUE;
//返回TRUE,表示成功执行本函数
}
|
入口点函数只应执行简单的初始化任务,不应调用任何其他 DLL 加载函数或终止函数。例如,在
入口点函数中,不应直接或间接调用
LoadLibrary 函数或
LoadLibraryEx 函数。此外,不应在进程终止时调用
FreeLibrary函数。
5如何导出编辑
要导出 DLL 函数,您可以向导出的 DLL 函数中添加函数关键字,也可以创建
模块定义文件(.def) 以列出导出的 DLL 函数。
向导出的 DLL 函数中添加函数关键字
__declspec(
dllexport)
要在
应用程序中使用导出的 DLL 函数,您必须使用以下关键字来声明要导入的各个函数:
__declspec(
dllimport)
通常
情况下,您最好使用一个包含 define 语句和 ifdef 语句的头文件,以便分隔导出语句和导入语句。
创建模块定义文件以列出导出的 DLL 函数
使用
模块定义文件来声明导出的 DLL 函数。当您使用
模块定义文件(.def)时,您不必向导出的 DLL 函数中添加函数关键字。在
模块定义文件中,您可以声明 DLL 的 LIBRARY 语句和 EXPORTS 语句。
6特别调用编辑
关于特定
情况下的调用,比如DLL函数中使用到了 Win32 API 或者将 C++ 生成的 DLL 供标准C语言使用,则需要注意以下一些情况:
如果使用到了 Win32 API,则应该使用关键字 __stdcall
在将 C++ 生成的 DLL 供标准C语言使用时,输出文件需要用 extern "C" 修饰,否则不能被标准
C语言调用。如果使用 __stdcall 调用方式,可能产生C不识别的修饰名,所以设置导出函数时要采用 .def 文件形式,而不是__declspec(dllexport) 形式。后者会进行修饰名转换,
C语言无法识别函数。
1
2
3
4
|
// SampleDLL.def
//
LIBRARY
"SampleDLL"
EXPORTS
|
7HelloWorld 示例 DLL 和应用程序编辑
在 Microsoft
Visual C++6.0 中,可以通过选择“Win32
动态链接库”
项目类型或“MFC
应用程序向导(
dll)”来创建 DLL。下面的
代码是一个在 Visual C++ 中通过使用“Win32 动态链接库”
项目类型创建的 DLL 的示例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// SampleDLL.cpp
#include "stdafx.h"
#define EXPORTING_DLL
#include "SampleDLL.h"
BOOL
APIENTRY DllMain(
HANDLE
hModule,
DWORD
ul_reason_for_call,
LPVOID
lpReserved) {
return
TRUE;
}
void
HelloWorld() {
MessageBox( NULL, TEXT(
"Hello World"
), TEXT(
"In a DLL"
), MB_OK);
}
// File: SampleDLL.h
#ifndef INDLL_H
#define INDLL_H
#ifdef EXPORTING_DLLextern
__declspec
(
dllexport
)
void
HelloWorld() ;
#elseextern
__declspec
(
dllimport
)
void
HelloWorld() ;
#endif
#endif
|
1
2
3
4
5
6
7
|
// SampleApp.cpp
#include "stdafx.h"
#include "SampleDLL.h"
int
APIENTRY WinMain(
HINSTANCE
hInstance,
HINSTANCE
hPrevInstance,
LPSTR
lpCmdLine,
int
nCmdShow) {
HelloWorld();
return
0;
}
|
在运行时动态链接中,您应使用与以下代码类似的代码来调用 SampleDLL.dll导出 DLL 函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//...
typedef
VOID
(*DLLPROC) (
LPTSTR
);
//...
HINSTANCE
hinstDLL;
DLLPROC HelloWorld;
BOOL
fFreeDLL;
hinstDLL = LoadLibrary(
"sampleDLL.dll"
);
if
(hinstDLL != NULL)
{
HelloWorld = (DLLPROC) GetProcAddress(hinstDLL,
"HelloWorld"
);
if
(HelloWorld != NULL)
(HelloWorld);
fFreeDLL = FreeLibrary(hinstDLL);
}
//...
|
8Windows API DLL 描述编辑
kernel32.dll
user32.dll
gdi32.dll
comdlg32.dll / lz32.dll / version.dll
comctl32.dll
一个新的 Windows 控件集合,比如 TreeView 和 RichTextBox 等等,最初这个是为了 Windows 95 而制作的,但是也使用于 NT 下。
mapi32.dll
电子邮件的专用函数。
netapi32.dll
访问和控制网络的函数。
odbc32.dll
ODBC功能的DLL。