打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
DLL

DLL - DLL说明

DLL文件即动态链接库文件,是一种可执行文件,它允许程序共享执行特殊任务所必需的代码和其他资源,一般来说,DLL是一种磁盘文件,以.dll、.DRV、.FON、.SYS和许多以.EXE为扩展名的系统文件都可以是DLL。它由全局数据、服务函数和资源组成,在运行时被系统加载到调用进程的虚拟空间中,成为调用进程的一部分。如果与其它 DLL 之间没有冲突,该文件通常映射到进程虚拟空间的同一地址上。DLL 模块中包含各种导出函数,用于向外界提供服务。DLL 可以有自己的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式;一个 DLL 在内存中只有一个实例;DLL 实现了代码封装性;DLL 的编制与具体的编程语言及编译器无关。

·DLL的产生

在dos时代,程序员是通过编写程序来达到预期的目的的,每实现一个目的就需要编写一个程序,这样下去,简单的还好,要是复杂的程序话,那是既浪费时间,又浪费青春。于是聪明的程序员们想出了一个办法,把的实现一定功能的程序模块存放在一个文件当中,以API函数形式存放在dll当中,当编写程序的时候,需要用到这个功能,那么直接从这个文件当中调用就可以了,于是就出现了dll——动态连接库。

这样,程序员把一些模块压入dll文件之后,在要运行程序的时候只需要调用动态链接库就可以了,而并不需要把dll加载到内存中。

通过使用 DLL,程序可以实现模块化,由相对独立的组件组成。例如,一个计帐程序可以按模块来销售。可以在运行时将各个模块加载到主程序中(如果安装了相应模块)。因为模块是彼此独立的,所以程序的加载速度更快,而且模块只在相应的功能被请求时才加载。

 

DLL - 动态链接库的分类

 

微软的Visual C++支持三种DLL,它们分别是Non-MFC Dll(非MFC动态库)、Regular Dll(常规DLL)、Extension Dll(扩展DLL)。

1、Non-MFCDLL(非MFC动态库)

  这种动态链接库指的是不用MFC的类库结构,直接用C语言写的DLL,其导出的函数是标准的C接口,能被非MFC或MFC编写的应用程序所调用。如果建立的DLL不需要使用MFC,那么应该建立Non-MFCDLL,因为使用MFC会增大用户库的大小,从而浪费用户的磁盘和内存空间。

2、RegularDLL(常规DLL)

  这种动态链接库和下述的ExtensionDll一样,是用MFC类库编写的,它的一个明显的特点是在源文件里有一个继承CWinApp的类(注意:此类DLL虽然从CWinApp派生,但没有消息循环),被导出的函数是C函数、C++类或者C++成员函数(注意不要把术语C++类与MFC的微软基础C++类相混淆),调用常规DLL的应用程序不必是MFC应用程序,只要是能调用类C函数的应用程序就可以,它们可以是在VisualC++、Delphi、VisualBasic、BorlandC等编译环境下利用DLL开发应用程序。常规DLL又可细分成静态链接到MFC和动态链接到MFC两种:    (1)静态连接到MFC的动态连接库只被VC的专业般和企业版所支持。该类DLL里的输出函数可以被任意Win32程序使用,包括使用MFC的应用程序。输出函数有如下形式:

extern"C"EXPORTYourExportedFunction();

  如果没有extern"C"修饰,输出函数仅仅能从C++代码中调用。

(2)动态链接到MFC的常规DLL里的输出函数可以被任意Win32程序使用,包括使用MFC的应用程序。所有从DLL输出的函数应该以如下语句开始:

AFX_MANAGE_STATE(AfxGetStaticModuleState())

此语句用来正确地切换MFC模块状态。

3、ExtensionDll(扩展DLL)

  这种动态链接库是使用MFC的动态链接版本所创建的,并且它只被用MFC类库所编写的应用程序所调用。例如你已经创建了一个从MFC的CtoolBar类的派生类用于创建一个新的工具栏,为了导出这个类,你必须把它放到一个MFC扩展的DLL中。扩展DLL和常规DLL不一样,它没有一个从CWinApp继承而来的类的对象,所以,开发人员必须在DLL中的DllMain函数添加初始化代码和结束代码。与常规DLL相比,扩展的DLL有如下不同点:    1)它没有一个从CWinApp派生的对象;

2)它必须有一个DLLMain函数;

3)DLLMain调用AfxInitExtensionModule函数,必须检查该函数的返回值,如果返回0,DLLMmain也返回0;  4)如果它希望输出CRuntimeClass类型的对象或者资源(Resources),则需要提供一个初始化函数来创建一个CDynLinkLibrary对象。并且,有必要把初始化函数输出;

5)使用扩展DLL的MFC应用程序必须有一个从CWinApp派生的类,而且,一般在InitInstance里调用扩展DLL的初始化函数。

DLL - 动态链接库的调用

动态链接库的调用可以分为两种:一种是隐式调用,一种是显示调用。

1、隐式的调用

  这种调用方式需要把产生动态连接库时产生的.LIB文件加入到应用程序的工程中,在使用DLL中的函数时,只须说明一下后就可以直接通过函数名调用DLL的输出函数,调用方法和程序内部其他的函数是一样的。隐式调用不需要调用LoadLibrary()和FreeLibrary()。程序员在建立一个DLL文件时,链接程序会自动生成一个与之对应的LIB导入文件。该文件包含了每一个DLL导出函数的符号名和可选的标识号,但是并不含有实际的代码。LIB文件作为DLL的替代文件被编译到应用程序项目中。

  当程序员通过隐式调用方式编译生成应用程序时,应用程序中的调用函数与LIB文件中导出符号相匹配,这些符号或标识号被写入到生成的EXE文件中。LIB文件中也包含了对应的DLL文件名(但不是完全的路径名),链接程序也将其存储在EXE文件内部。当应用程序运行过程中需要加载DLL文件时,Windows根据这些信息发现并加载DLL,然后通过符号名或标识号实现对DLL函数的动态链接。所有被应用程序调用的DLL文件都会在应用程序EXE文件加载时被加载在到内存中。

2、显式调用

  这种调用方式是指在应用程序中用LoadLibrary或MFC提供的AfxLoadLibrary显式的将自己所做的动态连接库调进来,并指定DLL的路径作为参数。LoadLibary返回HINSTANCE参数,应用程序在调用GetProcAddress函数时使用这一参数。当完成对动态链接库的导入以后,再使用GetProcAddress()获取想要引入的函数,该函数将符号名或标识号转换为DLL内部的地址,之后就可以象使用本应用程序自定义的函数一样来调用此引入函数了。在应用程序退出之前,应该用FreeLibrary或MFC提供的AfxFreeLibrary释放动态连接库。

DLL - 动态链接库的建立

1、Non-MFCDLL的建立

  每一个DLL必须有一个入口点,就象用C编写的应用程序时,必须有一个WINMAIN函数一样。在Non-MFCDLL中DllMain是一个缺省的入口函数,你不需要编写自己的DLL入口函数,用这个缺省的入口函数就能使动态链接库被调用时得到正确的初始化。如果应用程序的DLL需要分配额外的内存或资源,或者说需要对每个进程或线程初始化和清除操作时,需要在相应的DLL工程的.CPP文件中对DllMain()函数按照下面的格式书写。

BOOLAPIENTRYDllMain(HANDLEhModule,DWORDul_reason_for_call,LPVOIDlpReserved)  

{

  switch(ul_reason_for_call)

  {  

   caseDLL_PROCESS_ATTACH:

  .......

   caseDLL_THREAD_ATTACH:

  .......

  caseDLL_THREAD_DETACH:

  .......

  caseDLL_PROCESS_DETACH:

  .......

  }

  returnTRUE;

  }

  参数中,hMoudle是动态库被调用时所传递来的一个指向自己的句柄(实际上,它是指向_DGROUP段的一个选择符);

  ul_reason_for_call是一个说明动态库被调原因的标志,当进程或线程装入或卸载动态链接库的时候,操作系统调用入口函数,并说明动态链接库被调用的原因,它所有的可能值为:

  (1)DLL_PROCESS_ATTACH:进程被调用或调用LoadLibrary,DLL被链接到当前进程的地址空间并被初始化;

  (2)DLL_THREAD_ATTACH:当前进程创建一个新线程,DLL在新线程正文内被调用;

  (3)DLL_PROCESS_DETACH:调用DLL的进程被终止,DLL被卸载;

  (4)DLL_THREAD_DETACH:调用DLL的线程被终止,DLL被卸载;

  lpReserved为保留参数。

  如果在DLL中加入想要输出的函数、变量、C++类或其它函数,可以调用VC的关键字_declspec(dllexport)。2、MFCAppWizard[dll]方式下RegularDLL和ExtensionDLL的建立

  在MFCAppWizard[dll]下生成的DLL文件有三种方式:静态链接到MFC的常规DLL、动态链接到MFC的常规DLL以及MFC扩展DLL,在创建DLL是,要根据实际情况选择创建DLL的方式。

  静态链接到MFC的常规DLL和静态连接到MFC常规DLL的区别是:前者使用的是MFC的静态链接库,生成的DLL文件长度大,一般不使用这种方式;后者使用MFC的动态链接库,生成的DLL文件长度小;动态链接到MFC的常规DLL所有输出的函数应该以如下语句开始:

  AFX_MANAGE_STATE(AfxGetStaticModuleState())//此语句用来正确地切换MFC模块状态

  MFC扩展DLL的特点是用来建立MFC的派生类,Dll只被用MFC类库所编写的应用程序所调用。ExtensionDLLs和RegularDLLs不一样,它没有一个从CWinApp继承而来的类的对象,编译器默认了一个DLL入口函数DLLMain()作为对DLL的初始化,你可以在此函数中实现初始化,代码如下:

    BOOLWINAPIAPIENTRYDLLMain(HINSTANCEhinstDll,DWORDreason,LPVOIDflmpload)

  {

  switch(reason)

  {

  ……………//初始化代码;

  }

  returntrue;

  }

  参数hinstDll存放DLL的句柄,参数reason指明调用函数的原因,lpReserved是一个被系统所保留的参数。对于隐式链接是一个非零值,对于显式链接值是零。

总结

  在Windows操作系统中使用动态链接库(DLL)有很多优点,最主要的一点是多个应用程序、甚至是不同语言编写的应用程序可以共享一个DLL文件,真正实现了资源"共享",大大缩小了应用程序的执行代码,更加有效地利用了内存;使用DLL的另一个优点是DLL文件作为一个单独的程序模块,封装性、独立性好,在软件需要升级的时候,开发人员只需要修改相应的DLL文件就可以了,而且,当DLL中的函数改变后,如果没有修改参数,程序代码并不需要重新编译。这在编程时十分有用,大大提高了软件开发和维护的效率。
此外,可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。例如,您可能具有一个工资计算程序,而税率每年都会更改。当这些更改被隔离到 DLL 中以后,您无需重新生成或安装整个程序就可以应用更新。

下表说明了 Windows 操作系统中的一些作为 DLL 实现的文件:

ActiveX 控件 (.ocx) 文件
ActiveX 控件的一个示例是日历控件,它使您可以从日历中选择日期。
控制面板 (.cpl) 文件
.cpl 文件的一个示例是位于控制面板中的项。每个项都是一个专用 DLL。
设备驱动程序 (.drv) 文件
设备驱动程序的一个示例是控制打印到打印机的打印机驱动程序。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
做dll创建时有三种类型选择,分别做怎么解释啊多谢啊
动态链接库DLL编程(一)之简介
vc dll编程
使用c 开发excel插件 (第3章动态链接库(dynamic
动态链接库创建与使用
怎样用VB编写.DLL动态链接库文件 .
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服