动态链接库DLL编程.ppt
《动态链接库DLL编程.ppt》由会员分享,可在线阅读,更多相关《动态链接库DLL编程.ppt(61页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、VC+动态链接库动态链接库(DLL)编程编程1.概论概论先来阐述一下先来阐述一下DLL(DynamicLinkableLibrary)的概念,你可以简单的把的概念,你可以简单的把DLL看看成一种仓库,它提供给你一些可以直接成一种仓库,它提供给你一些可以直接拿来用的变量、函数或类。拿来用的变量、函数或类。在仓库的发展史上经历了在仓库的发展史上经历了“无库静态无库静态链接库动态链接库链接库动态链接库”的时代。的时代。对动态链接库,需建立如下概念:对动态链接库,需建立如下概念:(1)与具体的编程语言及编译器无关)与具体的编程语言及编译器无关只要遵循约定的只要遵循约定的DLL接口规范和调用方接口规范和
2、调用方式,用各种语言编写的式,用各种语言编写的DLL都可以相互都可以相互调用。调用。譬如譬如Windows提供的系统提供的系统DLL(其中包(其中包括了括了Windows的的API),在任何开发环境),在任何开发环境中都能被调用,不在乎其是中都能被调用,不在乎其是VisualBasic、VisualC+还是还是Delphi。(2)动态链接库随处可见)动态链接库随处可见在在Windows目录下的目录下的system32文件夹中会文件夹中会看到看到kernel32.dll、user32.dll和和gdi32.dll,windows的大多数的大多数API都包含在这些都包含在这些DLL中。中。kern
3、el32.dll中的函数主要处理内存管理和进程调度;user32.dll中的函数主要控制用户界面(MessageBox函数);gdi32.dll中的函数则负责图形方面的操作。(3)VC动态链接库的分类动态链接库的分类VisualC+支持三种支持三种DLL,它们分别是非,它们分别是非MFC动动态库、态库、MFC规则规则DLL、MFCExtensionDLL。非MFC动态库不采用MFC类库结构,其导出函数为标准的C接口,能被非MFC或MFC编写的应用程序所调用;MFC规则DLL包含一个继承自CWinApp的类,但其无消息循环;MFC扩展DLL采用MFC的动态链接版本创建,它只能被用MFC类库所编写
4、的应用程序所调用。2.静态链接库静态链接库在在VC+6.0中中new一个名称为一个名称为libTest的的staticlibrary工程工程,并新建并新建lib.h和和lib.cpp两个文件,两个文件,lib.h和和lib.cpp的源代码的源代码如下:如下:/文件:lib.h#ifndefLIB_H#defineLIB_HexternCintadd(intx,inty);/声明为C编译、连接方式的外部函数#endif/文件:lib.cpp#includelib.hintadd(intx,inty)returnx+y;#include#include.lib.h#pragmacomment(li
5、b,.debuglibTest.lib)/指定与静态库指定与静态库一起连接一起连接intmain(intargc,char*argv)printf(2+3=%d,add(2,3);选择选择tools、options、directories、libraryfiles菜单菜单或选项,填入库文件路径或选项,填入库文件路径4.非非MFCDLL在建立的工程中添加在建立的工程中添加lib.h及及lib.cpp文件,源代码文件,源代码如下:如下:/*文件名:文件名:lib.h*/#ifndefLIB_H#defineLIB_HexternCint_declspec(dllexport)add(intx,in
6、ty);#endif/*文件名:文件名:lib.cpp*/#includelib.hintadd(intx,inty)returnx+y;dllCall#include#includetypedefint(*lpAddFun)(int,int);/宏定义函数指针类型宏定义函数指针类型intmain(intargc,char*argv)HINSTANCEhDll;/DLL句柄句柄lpAddFunaddFun;/函数指针函数指针hDll=LoadLibrary(.DebugdllTest.dll);if(hDll!=NULL)addFun=(lpAddFun)GetProcAddress(hDll
7、,add);if(addFun!=NULL)intresult=addFun(2,3);printf(%d,result);FreeLibrary(hDll);return0;DLL的调用和静态链接库的调用有较大差异的调用和静态链接库的调用有较大差异首先,语句首先,语句typedefint(*lpAddFun)(int,int)定义了一个与定义了一个与add函数接受参数类型和返回值均相同的函数指针类型。随函数接受参数类型和返回值均相同的函数指针类型。随后,在后,在main函数中定义了函数中定义了lpAddFun的实例的实例addFun;其次,在函数其次,在函数main中定义了一个中定义了一个D
8、LLHINSTANCE句柄实句柄实例例hDll,通过,通过Win32Api函数函数LoadLibrary动态加载了动态加载了DLL模块并将模块并将DLL模块句柄赋给了模块句柄赋给了hDll;再次,在函数再次,在函数main中通过中通过Win32Api函数函数GetProcAddress得得到了所加载到了所加载DLL模块中函数模块中函数add的地址并赋给了的地址并赋给了addFun。经。经由函数指针由函数指针addFun进行了对进行了对DLL中中add函数的调用;函数的调用;最后,应用工程使用完最后,应用工程使用完DLL后,在函数后,在函数main中通过中通过Win32Api函数函数FreeLi
9、brary释放了已经加载的释放了已经加载的DLL模块。模块。声明导出函数声明导出函数DLL中导出函数的声明有两种方式:中导出函数的声明有两种方式:一种为给出的在函数声明中加上一种为给出的在函数声明中加上_declspec(dllexport);一种方式是采用模块定义一种方式是采用模块定义(.def)文件声文件声明明;在在DLL中想要中想要export的函数和数据定义前的函数和数据定义前添加添加_declspec(dllexport)关键字(对于)关键字(对于函数和变量定义,加在最前面;对于函数和变量定义,加在最前面;对于class定义,加在定义,加在class关键字关键字后)后);_decls
10、pec(dllexport)voidShowDlg(void)class_declspec(dllexport)class_name/导出类这样这样该函数和数据就会被添加到该函数和数据就会被添加到ET中。中。使用这种方法函数将按名字使用这种方法函数将按名字export。_declspec(dllexport)(.def)文件声明文件声明为为DLL创建一个创建一个.DEF文件(模块定义文文件(模块定义文件),并在件),并在build该该DLL时使用这个时使用这个.DEF文件。使用这种方法使你可以将函文件。使用这种方法使你可以将函数按序号数按序号export。在LINK选项卡中假如:/def:li
11、b.def将lib.def加入到工程中。lib.def;lib.def:导出导出DLL函数函数LIBRARYdllTestEXPORTSadd1.def文件的规则为:文件的规则为:(1)LIBRARY语句说明语句说明.def文件相应的文件相应的DLL;(2)EXPORTS语句后列出要导出函数的名称。可以在语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加文件中的导出函数名后加n,表示要导出函数的序号,表示要导出函数的序号为为n(在进行函数调用时,这个序号将发挥其作用);(在进行函数调用时,这个序号将发挥其作用);(3).def文件中的注释由每个注释行开始处的分号文件中的注释由每个
12、注释行开始处的分号(;)指定,且注释不能与语句共享一行。指定,且注释不能与语句共享一行。库的调试与查看库的调试与查看动态链接库中的导出接口可以使用动态链接库中的导出接口可以使用VisualC+的的Depends工具进行查看,工具进行查看,用用Depends打开系统目录中的打开系统目录中的MouseHook.dll.DLL的调用方式的调用方式1.隐式调用隐式调用:1.将DLL工程生成的.lib文件和.dll文件拷入当前工程所在的目录,并在*.cpp文件(的顶部添加:2.#pragmacomment(lib,RegularDll.lib)OR动态动态调用调用特点特点:是完全由编程者用是完全由编程者
13、用API函数加载和函数加载和卸载卸载DLL,程序员可以决定,程序员可以决定DLL文件何文件何时加载或不加载,显式链接在运行时决时加载或不加载,显式链接在运行时决定加载哪个定加载哪个DLL文件。文件。dllTest.dll在建立的工程中添加在建立的工程中添加lib.h及及lib.cpp文件,源代码如下:文件,源代码如下:/*文件名:文件名:lib.h*/#ifndefLIB_H#defineLIB_HexternCint_declspec(dllexport)add(intx,inty);#endif/*文件名:文件名:lib.cpp*/#includelib.hintadd(intx,inty
14、)returnx+y;调用调用dllTest.dll#include#includetypedefint(*lpAddFun)(int,int);/宏定义函数指针类型宏定义函数指针类型intmain(intargc,char*argv)HINSTANCEhDll;/DLL句柄句柄lpAddFunaddFun;/函数指针函数指针hDll=LoadLibrary(.DebugdllTest.dll);if(hDll!=NULL)addFun=(lpAddFun)GetProcAddress(hDll,add);if(addFun!=NULL)intresult=addFun(2,3);printf
15、(%d,result);FreeLibrary(hDll);DLL的的Export和和ImportDLL的的export是指将是指将DLL中的函数和数据输出中的函数和数据输出到其它程式中,以供其使用。到其它程式中,以供其使用。DLL的的import是是指使用指使用DLL的程式引入的程式引入DLL中的函数和数据。中的函数和数据。DLL的的exportDLL中包含有一个表,称为中包含有一个表,称为exporttable(以下简称(以下简称ET),其中包含了),其中包含了DLL中可以被外部程式使用的所有函数和数据中可以被外部程式使用的所有函数和数据的名字。的名字。只有记录在只有记录在ET中的函数和数
16、据才可以被外部程中的函数和数据才可以被外部程式所使用(如果没有式所使用(如果没有.DEF文件的话),其它所文件的话),其它所有没有记录在有没有记录在ET中的函数和数据都被视为是中的函数和数据都被视为是DLL私有的。私有的。DllMain函数函数Windows在加载在加载DLL的时候,需要一个入口函的时候,需要一个入口函数,就如同控制台或数,就如同控制台或DOS程序需要程序需要main函数、函数、WIN32程序需要程序需要WinMain函数一样。函数一样。在前面的例子中,在前面的例子中,DLL并没有提供并没有提供DllMain函函数,应用工程也能成功引用数,应用工程也能成功引用DLL,这是因为,
17、这是因为Windows在找不到在找不到DllMain的时候,系统会从的时候,系统会从其它运行库中引入一个不做任何操作的缺省其它运行库中引入一个不做任何操作的缺省DllMain函数版本,并不意味着函数版本,并不意味着DLL可以放弃可以放弃DllMain函数。函数。BOOLAPIENTRYDllMain(HANDLEhModule,DWORDul_reason_for_call,LPVOIDlpReserved)DllMain函数在函数在DLL被加载和卸载时被调用,在单个线程启动被加载和卸载时被调用,在单个线程启动和终止时,和终止时,DLLMain函数也被调用函数也被调用;ul_reason_fo
18、r_call指明了被调用的原因。原因共有指明了被调用的原因。原因共有4种,即种,即PROCESS_ATTACH、PROCESS_DETACH、THREAD_ATTACH和和THREAD_DETACH,以,以switch语句列语句列出。出。DLL导出变量导出变量/*文件名:文件名:lib.h*/#ifndefLIB_H#defineLIB_HexternintdllGlobalVar;#endif/*文件名:文件名:lib.cpp*/#includelib.h#includeintdllGlobalVar;BOOLAPIENTRYDllMain(HANDLEhModule,DWORDul_rea
19、son_for_call,LPVOIDlpReserved)dllGlobalVar=100;/在在dll被加载时,赋全局变量为被加载时,赋全局变量为100returnTRUE;文件名:文件名:lib.def;在在DLL中导出变量中导出变量LIBRARYdllTestEXPORTSdllGlobalVarDATA在主函数中引用在主函数中引用DLL中定义的全局变量:中定义的全局变量:#include#pragmacomment(lib,dllTest.lib)externint_declspec(dllimport)dllGlobalVar;/用用_declspec(dllimport)导导入入
20、intmain(intargc,char*argv)printf(%d,dllGlobalVar);dllGlobalVar=1;printf(%d,dllGlobalVar);return0;特别要注意特别要注意用用externintdllGlobalVar声明所导入的并不是声明所导入的并不是DLL中全局变量本身,而是其地址,应用程序中全局变量本身,而是其地址,应用程序必须通过强制指针转换来使用必须通过强制指针转换来使用DLL中的全局变中的全局变量。这一点,从量。这一点,从*(int*)dllGlobalVar可以看可以看出。因此在采用这种方式引用出。因此在采用这种方式引用DLL全局变量时,
21、全局变量时,千万不要进行这样的赋值操作:千万不要进行这样的赋值操作:dllGlobalVar=1;MFC规则规则DLLMFC规则规则DLL的概念体现在两方面:的概念体现在两方面:它是它是MFC的的“是MFC的”意味着可以在这种DLL的内部使用MFC;它是规则的它是规则的“是规则的”意味着它不同于MFC扩展DLL,在MFC规则DLL的内部虽然可以使用MFC,但是其与应用程序的接口不能是MFC。而MFC扩展DLL与应用程序的接口可以是MFC,可以从MFC扩展DLL中导出一个MFC类的派生类。RegularDLL能够被所有支持DLL技术的语言所编写的应用程序调用,当然也包括使用MFC的应用程序。Re
22、gularDLL分为两类:分为两类:(1)静态链接到)静态链接到MFC的规则的规则DLL静态链接到MFC的规则DLL与MFC库(包括MFC扩展DLL)静态链接,将MFC库的代码直接生成在.dll文件中。在调用这种DLL的接口时,MFC使用DLL的资源。因此,在静态链接到MFC的规则DLL中不需要进行模块状态的切换。使用这种方法生成的规则DLL其程序较大,也可能包含重复的代码。(2)动态链接到)动态链接到MFC的规则的规则DLL动态链接到MFC的规则DLL可以和使用它的可执行文件同时动态链接到MFCDLL和任何MFC扩展DLL。在使用了MFC共享库的时候,默认情况下,MFC使用主应用程序的资源句
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 动态 链接 DLL 编程
限制150内