第 4 讲 动态链接库 4.1 动态链接库 (DLL) 的概述 4.1.1 DLL 的定义 ...

20

Click here to load reader

description

第 4 讲 动态链接库 4.1 动态链接库 (DLL) 的概述 4.1.1 DLL 的定义 4.1.2 DLL 的种类 4.1.3 动态链接库和静态链接库的比较 4.2 DLL 的基本理论 4.2.1 DLL 入出口函数 4.2.2 DLL 的链接方式 4.2.3 DLL 动态链接库库函数的导出 4.2.4 从 DLL 中导出数据变量 4.3 用 VC++ 开发环境生成 DLL 4.3.1 用 VC++ 生成 WIN32 DLL 4.3.2 用 VC++ 的 MFC 生成的 DLL - PowerPoint PPT Presentation

Transcript of 第 4 讲 动态链接库 4.1 动态链接库 (DLL) 的概述 4.1.1 DLL 的定义 ...

Page 1: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

第 4 讲 动态链接库

4.1 动态链接库 (DLL) 的概述 4.1.1 DLL 的定义 4.1.2 DLL 的种类 4.1.3 动态链接库和静态链接库的比较4.2 DLL 的基本理论4.2.1 DLL 入出口函数 4.2.2 DLL 的链接方式4.2.3 DLL 动态链接库库函数的导出4.2.4 从 DLL 中导出数据变量4.3 用 VC++ 开发环境生成 DLL4.3.1 用 VC++ 生成 WIN32 DLL4.3.2 用 VC++ 的 MFC 生成的 DLL4.4 使用 DLL4.4.1 DLL 的使用 4.4.2 DLL 的调试4.5 用 VC++ 工具开发 DLL 的编程实例

Page 2: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.1 动态链接库 (DLL) 的概述DLL 特点:要求一个 DEF 文件;要求一个 DllMain() 的入口点,不是 WinMain() ; DLL 可以装入,但不能执行。 4.1.1 DLL 的定义 动态链接库:是应用程序中的一段程序,将它放在一个不同的容器内,是一个可以从主 .exe 文件中单独执行的模块 . 可以认为一个 DLL 就是其它应用程序在执行时 , 能够动态链接和调用的一组服务或函数 . DLL 中存放的一般是一些公共的子程序段或各种资源和数据 . 一个最大的特点 : 可以实现应用程序本地化 . 如在 DLL 中封装了各种语言 , 在安装时进行适当的选择就能实现本地化 .

Page 3: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.1.2 DLL 的种类主要有 Win32 DLL 和 MFC APPWizard DLL 两大类及相关子类。4.1.3 动态链接库和静态链接库的比较一个应用程序和函数的链接方式有两种:动态链接:在应用程序中不需要包含所要调用函数的代码,而只需要所调 DLL 函数的一些信息,如 DLL 位置及相应的函数名。与函数的链接到编译或运行时进行。静态链接:应用程序必须从静态链接库中取得所需调用函数的代码,并把这些代码放在应用程序的可执行代码中。如一般的库函数调用则属此类。

Page 4: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

DLL 的特点:

有利于不同的应用程序共享数据和资源;

多个应用程序可以使用内存中的动态链接库的单一映射,从而节约了程序运行和内存空间;

通过使用动态链接库,应用程序可以拆分为相对独立的功能模块,有利于应用程序的升级;

当多个应用程序需要使用相同的函数时,通过使用动态链接库,可以节约大量的硬盘空间。

Page 5: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.2 DLL 的基本理论应用程序在使用 DLL 中的内容之前,系统要调用入出口函数完成 DLL 的初始化和终止工作。4.2.1 DLL 入出口函数1 、 DllMain 函数 : 在一个 DLL 的调用和撤除时被调用,一般发生在应用程序使用 LoadLibrary 和 FreeLibrary 等函数及进程经线程启动和终止时。函数结构为:

BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD fdwReason , LPVOID lpvReserved){Switch (fdwReason){Case DLL_PROCESS_ATTACH:break;/DLL 映射到进程地址空间Case DLL_THREAD_ATTACH:break;/ 一个线程被创建Case DLL_THREAD_DETACH:break;/ 线程退出Case DLL_PROCESS_DETACH:break;}/DLL 从进程中解除映射Return TRUE;}

Page 6: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

其中 hInstance 是 DLL 的模块句柄 , lpvReserved 指定 DLL 初始化和清除的一些内容指针 ,fdwReason 表明调用 DllMain() 函数的原因 , 具体如下 :

标志 值 含义DLL_PROCESS_ATTACH

1 当一个 DLL 首次装入进程的地址空间时发送

DLL_THREAD_ATTACH

2 在连接 DLL 的进程中生成一个新线程时发送

DLL_THREAD_DETACH

3 在连接 DLL 的进程中一个线程终止时发送

DLL_PROCESS_DETACH

0 在应用程序终止或显式调用 FreeLibrary()使 DLL 脱离进程的地址空间时发送

Page 7: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

2 . MFC 的 Regular DLL 入出口

在 MFC 的 DLL 使用中 , 已编好了 DllMain() 函数 , 用户不必写 , 在装载 DLL 时调用其成员函数InitInstance, 在 DLL 退出时调用成员函数 ExitInstance, 所需要的初始化和终止工作在这两个函数中完成 .

Page 8: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.2.2 DLL 的链接方式DLL 中包含一个或多个函数 , 调用这些函数的过程

和编译 , 链接的过程是独立的 . 有两种链接方式 :隐式链接和显式链接 .

1. 隐式链接 DLL原理 : 先说明 DLL 的导入库文件 (lib), 因在库文件中

包含了一系列指向动态链接库的指针 . 应用程序通过库文件和 DLL 链接 , 调用 DLL 中的函数 .

应用程序在调用 DLL 时需以下信息 :A. 包含导出函数以及类声明的头文件 , 需要知道函

数名和函数接口信息 .B. DLL 的导入库文件 , 应用程序在编译链接需要 .C. 实际的 DLL 文件 , 应用程序在运行时调用它 .

Page 9: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

1. 显式链接 DLL原理 : 应用程序在运行时通过函数调用来显式装载

和卸载 DLL, 并通过函数指针来调用 DLL 的导出函数 , 这种方式主要用于灵活控制 DLL 库动态装入和装出的场合 .

使用 : 第一步调用函数 LoadLibrary 或 AfxLoadLibrary 装载 DLL 并得到模块句柄 . 原型如下 :

HINSTANCE LoadLibrary(LPCSTR lpLibFileName); 参数为要装入的 DLL 的文件名字 . 当此函数被多

次调用时 , 在进程中只有一份 DLL 程序和数据 ,系统通过计数器来标识 .

Page 10: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

第二步 : 调用函数 GetProcAddress 来获得导出函数的指针 . 函数原型如下 :FARPROC GetProcAddress(HMODULE hModul,LPCSTR lpProName);hMoudul 是 DLL 的实例句柄,参数 lpProName 是相应的函数名。第三步:在使用完后调用函数 FreeLibrary 或AfxFreeLibrary 来释放 DLL. FreeLibrary 原型为BOOL FreeLibrary( HINSTANCE hInstLib);参数是装入的 DLL 模块的句柄,调用一次,DLL 计数器值减一,最终回到 0 ,系统释放被 DLL占用的空间。

Page 11: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.2.3 DLL 动态链接库库函数的导出

动态链接库中的函数可以分为导出函数和内部函数。动态链接库中的函数主要有以下几种:( 1)在源程序中使用关键字: _declspec(dllexport).此函数可从一个 DLL 中输出数据 , 函数 , 类 , 类成员函数而不需要 DEF 文件 .原理 :根据一个指定的存储类属性 (extended-attribute)存储某个项数据 . 其属性主要有 :allocate(“segname”),dllimport,dllexport,naked 等 , 语法如下 :_declspec(extended_attribute) declarator; 具体使用有二种情况 :_declspec(dllexport) void_cdecl Function1(void);Class _declspec(dllexport) CExportCLass:public Cobject{……..}

Page 12: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

(2) 在 DEF 文件中通过 EXPORTS 来声明函数DEF 是由一个或多个描述 DLL 属性的语句组成的文本文件,主要有:LIBRARY 语句:用于指定 DLL 的内部名;DESCRIPTION 语句:用于描述 DLL 特性;SECTIONS 语句:用于设置段的属性,这些属性有: READ , WRITE , EXECUTE , SHARED ;EXPORTS 语句:用于列出被导出的函数名及相关信息;VERSION 语句:该 DLL 的版本号。

Page 13: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

例:LIBRARY “Dll”DESCRIPTION ‘Dll Windows Dynamic Link Library’EXPORTSFunction1 @1Function2 @2Function3 @3EXPORTS ……….……….库函数的声明如下 :Entryname[=internalname] [@ordinal[NONAME]]外部名 内部名 序号 不输出函数名

Page 14: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.2.4 从 DLL 中导出数据变量(1) 使用 DEF 文件 ,设置关键字 CONSTANT 导出 .通过用 CONSTANT 标志时 , 表明前面导出的不是函数 , 而是一个数据变量 .EXPORTSBvariable @4 CONSTANT

Extern BOOL bVariable ;// 程序中的应用(2) 可以在应用程序中使用关键字 _declspec(dllimport)引入对 DLL 导出的变量的作用 , 在 DLL 源程序中以_declspec(dllexport) 来说明要导出的变量 .

Page 15: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.3 用 VC++ 开发环境生成 DLL4.3.1 用 VC++ 生成 WIN32 DLL1. Win 32 的 DLL自动生成过程 : FILE->NEW->PROJECT->Win32 Dynamic-Link Li

brary->ok,然后选择相应的类型工程 .2. DLL 工程类型 :(1) 空 DLL 工程在需要时编写程序源文件 , 和 DEF 文件(2)简单的 DLL 工程只有 DllMain(),没有导出和其它变量或函数 , 不生成

DEF 文件 , 编译后也不产生 LIB 文件 .(3) 导出变量 , 函数和类的 DLL较为详细地建立了 DLL 中的一些基本成分 , 包括导

出关键字 _declspec(dllexport), 生成 LIB 文件 .

Page 16: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.3.2 用 VC++ 的 MFC 生成的 DLL1. MFC 类库的 DLL自动生成过程 : FILE->NEW->PROJECT->MFC AppWizard(dll) -

> ok,然后选择相应的类型工程 .2. MFC AppWizard DLL 类型 :(1) 静态链接 MFC 的 Regular DLL在内部使用 MFC 的 DLL 库 , 可被 MFC 和非MFC

的应用程序使用 ,若在工程建立时使用的是 MFC静态库 , 导出函数使用标准 C 语言接口 , 创建时自动生成 DEF 文件 , 如导出函数 :MyExportFunction() 用 :

extern “c” EXPORT MyExportFunction();(2) 动态链接 MFC 的 Regular DLL

Page 17: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

动态链接 MFC 的 Regular DLL 和静态链接 MFC 的Regular DLL 基本相似 , 最后都是由 CWinApp派生类的成员函数 InitInstance 和 ExitInstance 来完成 DLL 的初始化和应用程序调用结束时的终止 , 清理工作 .不同的是 :DLL 在建立时用的是 MFC 的动态共享库 .其导出函数的开头部分使用 AFX_MANAGE_STATE宏 .(3) 动态链接 MFC 的扩展 DLLMFC 的扩展 (Extension) DLL 是从已有的 MFC 类派生新类的 DLL, 它建立时作用 MFC 动态链接库 , 它的导出函数只能由使用 MFC 动态共享库的 MFC 应用程序调用 .

注 : 如果显示链接到这种 DLL 的应用程序是多线程的 ,则应使用 AfxLoadLibrary 和 AfxfreeLibray 来装载和卸载扩展 DLL, 而不要用 AfxLoadLibrary 和 AfxfreeLibray.

Page 18: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.4 使用 DLL4.4.1 DLL 的使用

调用 DLL 的应用程序在没有指定 DLL 位置时 ,默认位置如下 :(1) 含有该应用程序的目录(2) 当前执行所在目录(3)Windows 的系统目录 , 如 system目录(4)Windows目录(5) 在环境变量 PATH 中列出的目录

Page 19: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.4.2 DLL 的调试(1) 使用应用程序调试 DLL打开应用程序的工程 , 选择 Project->settings-> debug-> category->additional DLLs-> 指定调试的 DLL 文件 .(2) 使用 DLL 的工程调试 DLL打开 DLL 工程 , 选择 Project->settings-> debug -> category->additional DLLs-> 指定调试的 DLL 文件 .此时可以设置断点进行调试 .(3) 同时使用应用程序和 DLL 调试 DLL可以在同一个工作区中打开应用程序工程和 DLL 工程 , 如下 :选择 Project->Insert Project into Workspace-> Win32 debug 进行 DLL 程序调试 .

Page 20: 第 4 讲   动态链接库 4.1  动态链接库 (DLL) 的概述 4.1.1  DLL 的定义               4.1.2  DLL 的种类

4.5 用 VC++ 工具开发 DLL 的编程实例(见 P93-P102)