ImageVerifierCode 换一换
格式:DOC , 页数:64 ,大小:1.44MB ,
资源ID:3543781      下载积分:20 文钱
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,省得不是一点点
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.wenke99.com/d-3543781.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(VC++动态链接库(DLL)编程.doc)为本站会员(hw****26)主动上传,文客久久仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知文客久久(发送邮件至hr@wenke99.com或直接QQ联系客服),我们立即给予删除!

VC++动态链接库(DLL)编程.doc

1、 VC+动态链接库 (DLL)编程(一)理解库2005-10-20 23:36:00标签:VC+ 编程 DLL 推送到技术圈版 权 声 明 : 原 创 作 品 , 允 许 转 载 , 转 载 时 请 务 必 以 超 链 接 形 式 标 明 文 章 原 始 出 处 、 作 者 信 息 和 本声 明 。 否 则 将 追 究 法 律 责 任 。 http:/ e-mail:1.概论先来阐述一下 DLL(Dynamic Linkable Library)的概念,你可以简单的把 DLL 看成一种仓库,它提供给你一些可以直接拿来用的变量、函数或类。在仓库的发展史上经历了“无库静态链接库动态链接库”的时代。

2、静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都被直接包含在最终生成的 EXE文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。对动态链接库,我们还需建立如下概念:(1)DLL 的编制与具体的编程语言及编译器无关只要遵循约定的 DLL 接口规范和调用方式,用各种语言编写的 DLL 都可以相互调用。譬如

3、 Windows 提供的系统 DLL(其中包括了 Windows 的 API) ,在任何开发环境中都能被调用,不在乎其是 Visual Basic、Visual C+ 还是 Delphi。(2)动态链接库随处可见我们在 Windows 目录下的 system32文件夹中会看到 kernel32.dll、user32.dll 和gdi32.dll,windows 的大多数 API 都包含在这些 DLL 中。kernel32.dll 中的函数主要处理内存管理和进程调度;user32.dll 中的函数主要控制用户界面;gdi32.dll 中的函数则负责图形方面的操作。一般的程序员都用过类似 Mess

4、ageBox 的函数,其实它就包含在 user32.dll 这个动态链接库中。由此可见 DLL 对我们来说其实并不陌生。(3)VC 动态链接库的分类Visual C+支持三种 DLL,它们分别是 Non-MFC DLL(非 MFC 动态库) 、MFC Regular DLL(MFC 规则 DLL) 、MFC Extension DLL(MFC 扩展 DLL) 。非 MFC 动态库不采用 MFC 类库结构,其导出函数为标准的 C 接口,能被非 MFC 或MFC 编写的应用程序所调用; MFC 规则 DLL 包含一个继承自 CWinApp 的类,但其无消息循环;MFC 扩展 DLL 采用 MFC

5、的动态链接版本创建,它只能被用 MFC 类库所编写的应用程序所调用。由于本文篇幅较长,内容较多,势必需要先对阅读本文的有关事项进行说明,下面以问答形式给出。问:本文主要讲解什么内容?答:本文详细介绍了 DLL 编程的方方面面,努力学完本文应可以对 DLL 有较全面的掌握,并能编写大多数 DLL 程序。问:如何看本文?答:本文每一个主题的讲解都附带了源代码例程,可以随文下载(每个工程都经WINRAR 压缩) 。所有这些例程都由笔者编写并在 VC+6.0中调试通过。当然看懂本文不是读者的最终目的,读者应亲自动手实践才能真正掌握 DLL 的奥妙。问:学习本文需要什么样的基础知识?答:如果你掌握了 C

6、,并大致掌握了 C+,了解一点 MFC 的知识,就可以轻松地看懂本文。2.静态链接库对静态链接库的讲解不是本文的重点,但是在具体讲解 DLL 之前,通过一个静态链接库的例子可以快速地帮助我们建立“库”的概念。图1建立一个静态链接库如图1,在 VC+6.0中 new 一个名称为 libTest 的 static library 工程(单击此处下载本工程) ,并新建 lib.h 和 lib.cpp 两个文件,lib.h 和 lib.cpp 的源代码如下:/文件:lib.h#ifndef LIB_H#define LIB_Hextern “C“ int add(int x,int y); /声明为

7、C 编译、连接方式的外部函数#endif/文件:lib.cpp#include “lib.h“int add(int x,int y)return x + y;编译这个工程就得到了一个.lib 文件,这个文件就是一个函数库,它提供了 add 的功能。将头文件和.lib 文件提交给用户后,用户就可以直接使用其中的 add 函数了。标准 Turbo C2.0中的 C 库函数(我们用来的 scanf、printf、memcpy 、strcpy 等)就来自这种静态库。下面来看看怎么使用这个库,在 libTest 工程所在的工作区内 new 一个 libCall 工程。libCall 工程仅包含一个 m

8、ain.cpp 文件,它演示了静态链接库的调用方法,其源代码如下:#include #include “.lib.h“#pragma comment( lib, “.debuglibTest.lib“ ) /指定与静态库一起连接int main(int argc, char* argv)printf( “2 + 3 = %d“, add( 2, 3 ) );静态链接库的调用就是这么简单,或许我们每天都在用,可是我们没有明白这个概念。代码中#pragma comment( lib , “.debuglibTest.lib“ )的意思是指本文件生成的.obj 文件应与libTest.lib 一起连

9、接。如果不用#pragma comment 指定,则可以直接在 VC+中设置,如图2,依次选择 tools、options、directories、library files 菜单或选项,填入库文件路径。图2中加红圈的部分为我们添加的 libTest.lib 文件的路径。图2在 VC 中设置库文件路径这个静态链接库的例子至少让我们明白了库函数是怎么回事,它们是哪来的。我们现在有下列模糊认识了:(1)库不是个怪物,编写库的程序和编写一般的程序区别不大,只是库不能单独执行;(2)库提供一些可以给别的程序调用的东东,别的程序要调用它必须以某种方式指明它要调用之。以上从静态链接库分析而得到的对库的懵懂

10、概念可以直接引申到动态链接库中,动态链接库与静态链接库在编写和调用上的不同体现在库的外部接口定义及调用方式略有差异。3.库的调试与查看在具体进入各类 DLL 的详细阐述之前,有必要对库文件的调试与查看方法进行一下介绍,因为从下一节开始我们将面对大量的例子工程。由于库文件不能单独执行,因而在按下 F5(开始 debug 模式执行)或 CTRL+F5(运行)执行时,其弹出如图3所示的对话框,要求用户输入可执行文件的路径来启动库函数的执行。这个时候我们输入要调用该库的 EXE 文件的路径就可以对库进行调试了,其调试技巧与一般应用工程的调试一样。图3库的调试与“运行”通常有比上述做法更好的调试途径,那

11、就是将库工程和应用工程(调用库的工程)放置在同一 VC 工作区,只对应用工程进行调试,在应用工程调用库中函数的语句处设置断点,执行后按下 F11,这样就单步进入了库中的函数。第2节中的 libTest 和 libCall 工程就放在了同一工作区,其工程结构如图4所示。图4 把库工程和调用库的工程放入同一工作区进行调试上述调试方法对静态链接库和动态链接库而言是一致的。所以本文提供下载的所有源代码中都包含了库工程和调用库的工程,这二者都被包含在一个工作区内,这是笔者提供这种打包下载的用意所在。动态链接库中的导出接口可以使用 Visual C+的 Depends 工具进行查看,让我们用Depends

12、 打开系统目录中的 user32.dll,看到了吧?红圈内的就是几个版本的 MessageBox了!原来它真的在这里啊,原来它就在这里啊!图5 用 Depends 查看 DLL当然 Depends 工具也可以显示 DLL 的层次结构,若用它打开一个可执行文件则可以看出这个可执行文件调用了哪些 DLL。好,让我们正式进入动态链接库的世界,先来看看最一般的 DLL,即非 MFC DLL。VC+动态链接库(DLL)编程(二)非 MFC DLL2005-10-20 23:52:00标签:VC+ 编程 DLL 推送到技术圈版 权 声 明 : 原 创 作 品 , 允 许 转 载 , 转 载 时 请 务 必

13、 以 超 链 接 形 式 标 明 文 章 原 始 出 处 、 作 者 信 息 和 本声 明 。 否 则 将 追 究 法 律 责 任 。 http:/ MFC DLL4.1一个简单的 DLL第2节给出了以静态链接库方式提供 add 函数接口的方法,接下来我们来看看怎样用动态链接库实现一个同样功能的 add 函数。如图 6,在 VC+中 new 一个 Win32 Dynamic-Link Library 工程 dllTest(单击此处下载本工程附件) 。注意不要选择 MFC AppWizard(dll),因为用 MFC AppWizard(dll)建立的将是第5、6节要讲述的MFC 动态链接库。图

14、6 建立一个非 MFC DLL在建立的工程中添加 lib.h 及 lib.cpp 文件,源代码如下:/* 文件名:lib.h */#ifndef LIB_H#define LIB_Hextern “C“ int _declspec(dllexport)add(int x, int y);#endif/* 文件名:lib.cpp */#include “lib.h“int add(int x, int y)return x + y;与第2节对静态链接库的调用相似,我们也建立一个与 DLL 工程处于同一工作区的应用工程 dllCall,它调用 DLL 中的函数 add,其源代码如下:#includ

15、e #include typedef int(*lpAddFun)(int, int); /宏定义函数指针类型int main(int argc, char *argv)HINSTANCE hDll; /DLL 句柄lpAddFun addFun; /函数指针hDll = LoadLibrary(“.DebugdllTest.dll“);if (hDll != NULL)addFun = (lpAddFun)GetProcAddress(hDll, “add“);if (addFun != NULL)int result = addFun(2, 3);printf(“%d“, result);

16、FreeLibrary(hDll);return 0;分析上述代码,dllTest 工程中的 lib.cpp 文件与第2节静态链接库版本完全相同,不同在于 lib.h 对函数 add 的声明前面添加了 _declspec(dllexport)语句。这个语句的含义是声明函数 add 为 DLL 的导出函数。DLL 内的函数分为两种:(1)DLL 导出函数,可供应用程序调用;(2) DLL 内部函数,只能在 DLL 程序使用,应用程序无法调用它们。而应用程序对本 DLL 的调用和对第2 节静态链接库的调用却有较大差异,下面我们来逐一分析。首先,语句 typedef int ( * lpAddFun

17、)(int,int)定义了一个与 add 函数接受参数类型和返回值均相同的函数指针类型。随后,在 main 函数中定义了 lpAddFun 的实例 addFun;其次,在函数 main 中定义了一个 DLL HINSTANCE 句柄实例 hDll,通过 Win32 Api 函数LoadLibrary 动态加载了 DLL 模块并将 DLL 模块句柄赋给了 hDll;再次,在函数 main 中通过 Win32 Api 函数 GetProcAddress 得到了所加载 DLL 模块中函数 add 的地址并赋给了 addFun。经由函数指针 addFun 进行了对 DLL 中 add 函数的调用;最后

18、,应用工程使用完 DLL 后,在函数 main 中通过 Win32 Api 函数 FreeLibrary 释放了已经加载的 DLL 模块。通过这个简单的例子,我们获知 DLL 定义和调用的一般概念:(1)DLL 中需以某种特定的方式声明导出函数(或变量、类) ;(2)应用工程需以某种特定的方式调用 DLL 的导出函数(或变量、类) 。下面我们来对“特定的方式进行”阐述。4.2 声明导出函数DLL 中导出函数的声明有两种方式:一种为4.1节例子中给出的在函数声明中加上_declspec(dllexport),这里不再举例说明;另外一种方式是采用模块定义(.def) 文件声明,.def 文件为链接

19、器提供了有关被链接程序的导出、属性及其他方面的信息。下面的代码演示了怎样同.def 文件将函数 add 声明为 DLL 导出函数(需在 dllTest 工程中添加lib.def 文件):; lib.def : 导出 DLL 函数LIBRARY dllTestEXPORTSadd 1.def 文件的规则为:(1)LIBRARY 语句说明.def 文件相应的 DLL;(2)EXPORTS 语句后列出要导出函数的名称。可以在.def 文件中的导出函数名后加n,表示要导出函数的序号为 n(在进行函数调用时,这个序号将发挥其作用) ;(3).def 文件中的注释由每个注释行开始处的分号 (;) 指定,且

20、注释不能与语句共享一行。由此可以看出,例子中 lib.def 文件的含义为生成名为“dllTest” 的动态链接库,导出其中的 add 函数,并指定 add 函数的序号为 1。4.3 DLL 的调用方式在4.1节的例子中我们看到了由“LoadLibrary-GetProcAddress-FreeLibrary” 系统 Api 提供的三位一体“DLL 加载-DLL 函数地址获取-DLL 释放”方式,这种调用方式称为 DLL 的动态调用。动态调用方式的特点是完全由编程者用 API 函数加载和卸载 DLL,程序员可以决定 DLL 文件何时加载或不加载,显式链接在运行时决定加载哪个 DLL 文件。与动

21、态调用方式相对应的就是静态调用方式, “有动必有静” ,这来源于物质世界的对立统一。 “动与静” ,其对立与统一竟无数次在技术领域里得到验证,譬如静态 IP 与 DHCP、静态路由与动态路由等。从前文我们已经知道,库也分为静态库与动态库 DLL,而想不到,深入到 DLL 内部,其调用方式也分为静态与动态。“动与静”,无处不在。 周易已认识到有动必有静的动静平衡观, 易系辞曰:“动静有常,刚柔断矣” 。哲学意味着一种普遍的真理,因此,我们经常可以在枯燥的技术领域看到哲学的影子。静态调用方式的特点是由编译系统完成对 DLL 的加载和应用程序结束时 DLL 的卸载。当调用某 DLL的应用程序结束时,

22、若系统中还有其它程序使用该 DLL,则 Windows 对 DLL 的应用记录减1,直到所有使用该 DLL 的程序都结束时才释放它。静态调用方式简单实用,但不如动态调用方式灵活。下面我们来看看静态调用的例子(单击此处下载本工程附件) ,将编译 dllTest 工程所生成的.lib 和.dll文件拷入 dllCall 工程所在的路径,dllCall 执行下列代码:#pragma comment(lib,“dllTest.lib“)/.lib 文件中仅仅是关于其对应 DLL 文件中函数的重定位信息extern “C“ _declspec(dllimport) add(int x,int y);in

23、t main(int argc, char* argv)int result = add(2,3);printf(“%d“,result);return 0;由上述代码可以看出,静态调用方式的顺利进行需要完成两个动作:(1)告诉编译器与 DLL 相对应的 .lib 文件所在的路径及文件名,#pragma comment(lib,“dllTest.lib“)就是起这个作用。程序员在建立一个 DLL 文件时,连接器会自动为其生成一个对应的.lib 文件,该文件包含了 DLL 导出函数的符号名及序号(并不含有实际的代码) 。在应用程序里,.lib 文件将作为 DLL 的替代文件参与编译。(2)声明导

24、入函数, extern “C“ _declspec(dllimport) add(int x,int y)语句中的_declspec(dllimport)发挥这个作用。静态调用方式不再需要使用系统 API 来加载、卸载 DLL 以及获取 DLL 中导出函数的地址。这是因为,当程序员通过静态链接方式编译生成应用程序时,应用程序中调用的与.lib 文件中导出符号相匹配的函数符号将进入到生成的 EXE 文件中, .lib 文件中所包含的与之对应的 DLL 文件的文件名也被编译器存储在 EXE 文件内部。当应用程序运行过程中需要加载 DLL 文件时, Windows 将根据这些信息发现并加载DLL,然

25、后通过符号名实现对 DLL 函数的动态链接。这样,EXE 将能直接通过函数名调用 DLL 的输出函数,就象调用程序内部的其他函数一样。4.4 DllMain 函数Windows 在加载 DLL 的时候,需要一个入口函数,就如同控制台或 DOS 程序需要 main 函数、WIN32程序需要 WinMain 函数一样。在前面的例子中,DLL 并没有提供 DllMain 函数,应用工程也能成功引用 DLL,这是因为 Windows 在找不到 DllMain 的时候,系统会从其它运行库中引入一个不做任何操作的缺省 DllMain 函数版本,并不意味着 DLL 可以放弃 DllMain 函数。根据编写规范,Windows 必须查找并执行 DLL 里的 DllMain 函数作为加载 DLL 的依据,它使得 DLL得以保留在内存里。这个函数并不属于导出函数,而是 DLL 的内部函数。这意味着不能直接在应用工程中引用 DllMain 函数, DllMain 是自动被调用的。我们来看一个 DllMain 函数的例子(单击此处下载本工程附件) 。BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。