已阅读5页,还剩9页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
动态链接库DLL目录动态链接库DLL1目录1DLL概述2DLL定义2DLL的种类2动态链接库和静态链接库的比较2DLL的特点:2DLL的基本理论2DLL入出口函数3DLL的链接方式3隐式连接3显式链接DLL4DLL动态链接库库函数的导出4从DLL中导出数据变量5用VC+开发环境生成DLL5用VC+生成WIN32 DLL5用VC+的MFC生成的 DLL5使用DLL6DLL的使用6DLL的调试6DLL概述DLL特点:要求一个DEF文件;要求一个DllMain()的入口点,不是WinMain();DLL可以装入,但不能执行。DLL定义动态链接库:是应用程序中的一段程序,将它放在一个不同的容器内,是一个可以从主.exe文件中单独执行的模块.可以认为一个DLL就是其它应用程序在执行时,能够动态链接和调用的一组服务或函数.DLL中存放的一般是一些公共的子程序段或各种资源和数据.一个最大的特点:可以实现应用程序本地化.如在DLL中封装了各种语言,在安装时进行适当的选择就能实现本地化.DLL的种类主要有Win32 DLL和MFC APPWizard DLL两大类及相关子类。动态链接库和静态链接库的比较动态链接:在应用程序中不需要包含所要调用函数的代码,而只需要所调DLL函数的一些信息,如DLL位置及相应的函数名。与函数的链接到编译或运行时进行。静态链接:应用程序必须从静态链接库中取得所需调用函数的代码,并把这些代码放在应用程序的可执行代码中。如一般的库函数调用则属此类。DLL的特点: 有利于不同的应用程序共享数据和资源; 多个应用程序可以使用内存中的动态链接库的单一映射,从而节约了程序运行和内存空间; 通过使用动态链接库,应用程序可以拆分为相对独立的功能模块,有利于应用程序的升级; 当多个应用程序需要使用相同的函数时,通过使用动态链接库,可以节约大量的硬盘空间。DLL的基本理论应用程序在使用DLL中的内容之前,系统要调用入出口函数完成DLL的初始化和终止工作。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;其中hInstance是DLL的模块句柄, lpvReserved 指定DLL初始化和清除的一些内容指针,fdwReason表明调用DllMain()函数的原因,具体如下: 标志值含义DLL_PROCESS_ATTACH1当一个DLL首次装入进程的地址空间时发送DLL_THREAD_ATTACH2在连接DLL的进程中生成一个新线程时发送DLL_THREAD_DETACH3在连接DLL的进程中一个线程终止时发送DLL_PROCESS_DETACH0在应用程序终止或显式调用FreeLibrary()使DLL脱离进程的地址空间时发送MFC的 Regular DLL 入出口在MFC的DLL使用中,已编好了DllMain()函数,用户不必写,在装载DLL时调用其成员函数InitInstance,在DLL退出时调用成员函数ExitInstance, 所需要的初始化和终止工作在这两个函数中完成.DLL的链接方式DLL中包含一个或多个函数,调用这些函数的过程和编译,链接的方式包括显式连接和隐式链接。隐式连接!l 原理:先说明DLL的导入库文件(lib),因在库文件包含了一系列指向动态链接库的指针.应用程序通过库文件和DLL链接,调用DLL中的函数.l 应用程序在调用DLL时需以下信息:1. 包含导出函数以及类声明的头文件,需要知道函数名和函数接口信息.2. DLL的导入库文件,应用程序在编译链接需要.3. 实际的DLL文件,应用程序在运行时调用它.l 具体做法:l 第一步,代码声明。有几种导出成员函数的方法用extern进行修饰,实例代码如下:extern int add(int a, int b);extern int subtract(int a, int b);void CDllTextDlg:OnButton1() / TODO: Add your control notification handler code hereCString str;str.Format(3+5=%d,add(3,5);MessageBox(str);void CDllTextDlg:OnButton2() / TODO: Add your control notification handler code hereCString str;str.Format(3-5=%d,subtract(3,5);MessageBox(str);或者:(后者专门针对动态链接库,效率更高)_declspec(dllimport) int add(int a, int b);_declspec(dllimport) int subtract(int a, int b);或者:使用dll生成方提供的头文件。头文件dll1.h:(这个文件dll生成者不一定需要,仅供调用者使用,告诉他们这个dll定义了哪些方法和变量)_declspec(dllimport) int add(int a, int b);_declspec(dllimport) int subtract(int a, int b);调用方:#include ./dllp1/dll1.hl 第二步,添加Link库文件Dll文件生成的同时,一个.lib链接库文件也会生出。其功能是间接调用者的程序和dll文件,它描述了dll的基本状况。l 第三步:部署dll文件到调用者能找到的位置。显式链接DLLl 原理:应用程序在运行时通过函数调用来显式装载和卸载DLL,并通过函数指针来调用DLL的导出函数,这种方式主要用于灵活控制DLL库动态装入和装出的场合.l 使用:第一步:调用函数LoadLibrary或AfxLoadLibrary装载DLL并得到模块句柄.原型如下: HINSTANCE LoadLibrary(LPCSTR lpLibFileName);参数为要装入的DLL的文件名字.当此函数被多次调用时,在进程中只有一份DLL程序和数据,系统通过计数器来标识. 第二步:调用函数GetProcAddress来获得导出函数的指针.函数原型如下:FARPROC GetProcAddress(HMODULE hModul,LPCSTR lpProName);hMoudul是DLL的实例句柄,参数lpProName是相应的函数名。第三步:在使用完后调用函数FreeLibrary或AfxFreeLibrary 来释放DLL. FreeLibrary原型为BOOL FreeLibrary(HINSTANCE hInstLib);参数是装入的DLL模块的句柄,调用一次,DLL计数器值减一,最终回到0,系统释放被DLL占用的空间。l 好处:a) 不需要其它文件(例如link时的.lib文件);b) 速度较快,但耗费资源Code:voidCdll_testDlg:OnBnClickedButton1()/TODO:在此添加控件通知处理程序代码HINSTANCEhInst;hInst=LoadLibrary(Ldll1.dll);typedefint(*ADDPTR)(inta,intb);/定义一个函数指针ADDPTRadd;/add函数指针变量if(hInst!=NULL)/载入DLL成功add=(ADDPTR)GetProcAddress(hInst,add);/去除dll中函数名为add的这个函数的地址/如果发生了函数的名字改编这里是不是就会失败啊!if(NULL!=add)/找到DLL中的add函数CStringstr;/*注意:因为这里编译器默认定义了unicode了吧,解决办法如下Format(L%c,s);或者Format(_T(%c),s);*/str.Format(L5+3=%d,add(5,3);MessageBox(str);elseMessageBox(L获取函数地址失败);elseMessageBox(L加载DLL失败);Note:GetProcAddress方法因为是运行时载入,没有编译名字改编,所有使用的名字必须是dll中的改编后的名字。最好是都不改。关于头文件1, dll生成者不一定需要,可以提供给使用dll的client,因为他们一般不知道dll内部有哪些函数和变量可以使用,因而在他们的程序内定义变量和函数比较麻烦。2, 当然,这个头文件也可以供dll生成者使用,以提供一些辅助功能。这样.h文件同时供dll生成方和调用者使用,而两者可以实现不同的功能。例如:头文件:dll1.h#ifdef DLL1_API#else#define DLL1_API _declspec(dllimport)#endifDLL1_API int add(int a, int b);DLL1_API int subtract(int a, int b);源文件:#define DLL1_API _declspec(dllexport)#include dll1.hDLL1_API int add (int a, int b)return a+b;DLL1_API int subtract(int a, int b)return a-b;成员类的导出和导入导出:在头文件中定义,然后再实现头文件dll1.h#ifdef DLL1_API#else#define DLL1_API _declspec(dllimport)#endifDLL1_API int add(int a, int b);DLL1_API int subtract(int a, int b);class DLL1_API Pointpublic:void output(int x, int y);源文件dll1.cpp#define DLL1_API _declspec(dllexport)#include dll1.h#include #include DLL1_API int add (int a, int b)DLL1_API int subtract(int a, int b)void Point:output(int x, int y)HWND hwnd=GetForegroundWindow();/获得调用者的窗口的句柄,当前正在使用的窗口 HDC hdc=GetDC(hwnd); char buf20; memset(buf,0,20); sprintf(buf,x=%d,y=%d,x,y);/字符数组的格式化 TextOut(hdc,0,0,buf,strlen(buf); ReleaseDC(hwnd,hdc);调用:更新头文件,lib文件,dll文件,然后实现调用代码:#include ./dllp1/dll1.hvoid CDllTextDlg:OnButton3() / TODO: Add your control notification handler code herePoint pt;pt.output(5,3);导出类的部分方法:class Pointpublic:DLL_API void output(int x, int y); Void output2(int x, int y);不同编译器(C vs C+)的名字改编为了实现重载,C+编译器会对函数名进行名字改编,这个规则是一定的。如果再由C程序去调用,会找不到函数。而如果采用同样的C+编译器,因为他知道转换后的名字会是什么,所以能找到。但是不同的C+编译器可能会因为改编规则不同而无法访问。因此,有时候希望名字不变。代码:dll1.h#ifdef DLL1_API#else#define DLL1_API extern C _declspec(dllimport)#endifDLL1_API int add(int a, int b);DLL1_API int subtract(int a, int b);dll1.cpp#define DLL1_API extern C _declspec(dllexport)#include dll1.h#include #include DLL1_API int add (int a, int b)return a+b;DLL1_API int subtract(int a, int b)return a-b;使用dump观察函数名:E:VCC-spacedllp1Debugdumpbin -exports dllp1.dllMicrosoft (R) COFF Binary File Dumper Version 6.00.8168Copyright (C) Microsoft Corp 1992-1998. All rights reserved.Dump of file dllp1.dllFile Type: DLL Section contains the following exports for dllp1.dll 0 characteristics 4AB228D6 time date stamp Thu Sep 17 20:17:26 2009 0.00 version 1 ordinal base 2 number of functions 2 number of names ordinal hint RVA name 1 0 0000100A add 2 1 00001005 subtract Summary 4000 .data 1000 .idata 2000 .rdata 2000 .reloc 28000 .text如果不加“extern “C”,结果会是: ordinal hint RVA name 2 1 0000100A ?addYAHHHZ 4 3 00001005 ?subtractYAHHHZNote:a) Extern “C”不适合类的成员函数b) 调用约定发生改变,函数名也会变化。例如下面的实现,_stdcall导致编译约定被设置为pascal的编译方式,名字会改变:源文件:DLL1_API int _stdcall add (int a, int b)return a+b;DLL1_API int _stdcall subtract(int a, int b)return a-b;头文件DLL1_API int _stdcall add(int a, int b);DLL1_API int _stdcall subtract(int a, int b);使用dumpbin观察的结果:(下划线+函数名+参数字节数(这里两个int为8字节) ordinal hint RVA name 1 0 00001005 _add8 2 1 0000100A _subtract8c) C,C+,delphi调用带来的混乱和不便,可通过模块定义文件来解决DLL动态链接库库函数的导出动态链接库中的函数可以分为导出函数和内部函数。动态链接库中的函数主要有以下几种:(1) 在源程序中使用关键字:_declspec(dllexport).此函数可从一个DLL中输出数据,函数,类,类成员函数而不需要DEF文件.原理:根据一个指定的存储类属性(extended-attribute)存储某个项数据.其属性主要有:allocate(“segname”),dllimport,dllexport,naked等,语法如下:_declspec(extended_attribute) declarator;具体使用有二种情况:i. _declspec(dllexport) void_cdecl Function1(void);ii. Class _declspec(dllexport) CExportCLass:public Cobject .(2) 在DEF文件中通过EXPORTS来声明函数DEF是由一个或多个描述DLL属性的语句组成的文本文件,主要有:LIBRARY语句:用于指定DLL的内部名;DESCRIPTION语句:用于描述DLL特性;SECTIONS语句:用于设置段的属性,这些属性有: READ,WRITE,EXECUTE,SHARED;EXPORTS语句:用于列出被导出的函数名及相关信息;VERSION语句:该DLL的版本号。例:LIBRARY “Dll”DESCRIPTION Dll Windows Dynamic Link LibraryEXPORTSFunction1 1Function2 2Function3 3EXPORTS .库函数的声明如下:Entryname=internalname ordinalNONAME外部名 内部名 序号 不输出函数名模块定义文件的特点a) 改变编译环境(例如对函数名加“_stdcall”),名字不便,仍然是def文件中定义从DLL中导出数据变量(1) 使用DEF文件,设置关键字CONSTANT导出.通过用CONSTANT标志时,表明前面导出的不是函数,而是一个数据变量.EXPORTSBvariable 4 CONSTANTExtern BOOL bVariable ;/程序中的应用(2) 可以在应用程序中使用关键字 _declspec(dllimport)引入对DLL导出的变量的作用,在DLL源程序中以_declspec(dllexport)来说明要导出的变量.用VC+开发环境生成DLL用VC+生成WIN32 DLL1. Win 32的DLL自动生成过程:FILE-NEW-PROJECT-Win32 Dynamic-Link Library-ok,然后选择相应的类型工程.2. DLL工程类型:l 空DLL工程:在需要时编写程序源文件,和DEF文件l 简单的DLL工程:只有DllMain(),没有导出和其它变量或函数,不生成DEF文件,编译后也不产生LIB文件.l 导出变量,函数和类的DLL:较为详细地建立了DLL中的一些基本成分,包括导出关键字_declspec(dllexport),生成LIB文件.用VC+的MFC生成的 DLL1. MFC类库的DLL自动生成过程: FILE-NEW-PROJECT-MFC AppWizard(dll) - ok,然后选择相应的类型工程。2. MFC AppWizard DLL类型l 静态链接MFC的 Regular DLL在内部使用MFC的DLL库,可被MFC和非MFC的应用程序使用,若在工程建立时使用的是MFC静态库,导出函数使用标准C语言接口,创建时自动生成D
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 强化心理健康科学预防疾病高一主题班会课件
- 构建心理防线勇于面对挑战小学四年级主题班会课件
- 就项目合同签订事宜的确认函3篇
- 科学预防传染疾病共建和谐校园小学主题班会课件
- 中华传统节日:了解习俗传承文化小学主题班会课件
- 关于招聘新员工通知函(3篇)
- 小学主题班会课件:培养诚信美德
- 冶金工业钢铁生产技术与环保技术应用
- 项目进度延期审批确认函3篇
- 重要设备故障快速修复策略预案
- 紧急维修服务作业规范
- 2025年江西省九江市八年级地生会考真题试卷(含答案)
- 2026年安全生产月危险化学品企业排查整治风险隐患培训课件
- 2026中国AOPA电动超轻型飞行器行业发展报告
- 员工绩效薪酬激励管理办法
- (2025)SRLF、GFRUP临床实践指南:重症监护病房的营养支持解读
- 2026中国磷化铟粉末行业发展态势及供需前景预测报告
- 2026年毕节工业职业技术学院教师招聘笔试备考试题及答案解析
- 加油站安全隐患整改实施方案
- 2026中国邮政集团有限公司安徽省分公司社会招聘备考题库及完整答案详解(考点梳理)
- 吉林大学挂科制度
评论
0/150
提交评论