|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
我也不知道,我原来理解的,NET就是C++编程,只是与JAVA相对,呵呵。以为.ET就是高级C++编程。静态|链接|成绩 提要
本文申明甚么是静态链接库(DLL)和在利用DLL时大概产生的各类成绩。
然后,本文申明在开辟您本人的DLL时应当思索的一些初级成绩。在申明甚么是DLL的过程当中,本文将申明静态链接办法、DLL依附性、DLL出口点、导出DLL函数和DLL妨碍扫除工具。
本文最初将从较高的条理对DLL与Microsoft.NETFramework程序集作一对照。
简介
关于“合用于”一节中列出的MicrosoftWindows操纵体系,操纵体系的大批功效是由静态链接库(DLL)供应的。别的,当您在这些Windows操纵体系之一上运转某一程序时,该程序的良多功效多是由DLL供应的。比方,某些程序大概包括良多分歧的模块,而该程序的每一个模块都包括在DLL中并从平分发。
利用DLL有助于增进代码的模块化、代码重用、内存的无效利用和削减所占用的磁盘空间。因而,操纵体系和程序可以更快地加载和运转,而且在盘算机中占用较少的磁盘空间。
当程序利用DLL时,一个称为依附性的成绩大概招致该程序没法运转。当程序利用DLL时,就会创立一个依附项。假如其他程序改写和破坏了该依附项,本来的谁人程序便可能没法乐成运转。
在引进Microsoft.NETFramework以后,年夜多半依附性成绩都已经由过程利用程序集打消了。
甚么是DLL?
DLL是一个包括可由多个程序同时利用的代码和数据的库。比方,在Windows操纵体系中,Comdlg32DLL实行与对话框有关的罕见函数。因而,每一个程序都可使用该DLL中包括的功效来完成“翻开”对话框。这有助于增进代码重用和内存的无效利用。
经由过程利用DLL,程序能够完成模块化,由绝对自力的组件构成。比方,一个算帐程序能够按模块来发卖。能够在运转时将各个模块加载到主程序中(假如安装了响应模块)。由于模块是相互自力的,以是程序的加载速率更快,并且模块只在响应的功效被哀求时才加载。
别的,能够更加简单地将更新使用于各个模块,而不会影响该程序的其他部分。比方,您大概具有一个人为盘算程序,而税率每一年城市变动。当这些变动被断绝到DLL中今后,您无需从头天生或安装全部程序就能够使用更新。
下表申明了Windows操纵体系中的一些作为DLL完成的文件:•ActiveX控件(.ocx)文件
ActiveX控件的一个示例是日历控件,它使您能够从日历当选择日期。
•把持面板(.cpl)文件
.cpl文件的一个示例是位于把持面板中的项。每一个项都是一个公用DLL。
•设备驱动程序(.drv)文件
设备驱动程序的一个示例是把持打印到打印机的打印机驱动程序。
DLL的长处
下表申明了当程序利用DLL时供应的一些长处:•利用较少的资本
当多个程序利用统一个函数库时,DLL能够削减在磁盘和物理内存中加载的代码的反复量。这不但能够年夜年夜影响在前台运转的程序,并且能够年夜年夜影响其他在Windows操纵体系上运转的程序。
•推行模块式系统布局
DLL有助于增进模块式程序的开辟。这能够匡助您开辟请求供应多个言语版本的年夜型程序或请求具有模块式系统布局的程序。模块式程序的一个示例是具有多个能够在运转时静态加载的模块的算帐程序。
•简化部署和安装
当DLL中的函数必要更新或修复时,部署和安装DLL不请求从头创建程序与该DLL的链接。别的,假如多个程序利用统一个DLL,那末多个程序都将从该更新或修复中获益。当您利用按期更新或修复的第三方DLL时,此成绩大概会更频仍地呈现。
DLL依附项
当某个程序或DLL利用其他DLL中的DLL函数时,就会创立依附项。因而,该程序就不再是自力的,而且假如该依附项被破坏,该程序便可能碰到成绩。比方,假如产生以下操纵之一,则该程序大概没法运转:•依附DLL晋级到新版本。
•修复了依附DLL。
•依附DLL被其初期版本掩盖。
•从盘算机中删除依附DLL。
这些操纵一般称为DLL抵触。假如没有强迫完成向后兼容性,则该程序大概没法乐成运转。
下表申明了为了匡助最年夜限制地削减依附性成绩而在MicrosoftWindows2000和较高版本的Windows操纵体系中引进的变动:•Windows文件回护
在Windows文件回护中,操纵体系克制未经受权的代办署理更新或删除体系DLL。因而,当程序安装操纵实验删除或更新被界说为体系DLL的DLL时,Windows文件回护将寻觅无效的数字署名。
•公用DLL
经由过程公用DLL可使程序制止蒙受对共享DLL举行的变动。公用DLL利用版本特定信息或空.local文件来强迫请求程序所利用的DLL的版本。要利用公用DLL,请在程序根文件夹中查找DLL。然后,关于新程序,请向该DLL中增加版本特定信息。关于旧程序,请利用空.local文件。每一个办法都告知操纵体系利用位于程序根文件夹中的公用DLL。
DLL妨碍扫除工具
可使用多个工具来匡助您办理DLL成绩。以下是个中的部合作具。
DependencyWalker
DependencyWalker工具能够递回扫描以寻觅程序所利用的一切依附DLL。当您在DependencyWalker中翻开程序时,DependencyWalker会实行以下反省:•DependencyWalker反省是不是丧失DLL。
•DependencyWalker反省是不是存在有效的程叙文件或DLL。
•DependencyWalker反省导进函数和导出函数是不是婚配。
•DependencyWalker反省是不是存在轮回依附性毛病。
•DependencyWalker反省是不是存在因为针对另外一分歧操纵体系而有效的模块。
经由过程利用DependencyWalker,您能够纪录程序利用的一切DLL。这大概有助于制止和改正未来大概产生的DLL成绩。当您安装MicrosoftVisualStudio6.0时,DependencyWalker将位于以下目次中:
driveProgramFilesMicrosoftVisualStudioCommonTools
DLLUniversalProblemSolver
DLLUniversalProblemSolver(DUPS)工具用于考核、对照、纪录和显现DLL信息。下表申明了构成DUPS工具的有用工具:•Dlister.exe
该有用工具列举盘算机中的一切DLL,而且将此信息纪录到一个文本文件或数据库文件中。
•Dcomp.exe
该有用工具对照在两个文本文件中列出的DLL,并发生包括差别的第三个文本文件。
•Dtxt2DB.exe
该有用工具将经由过程利用Dlister.exe有用工具和Dcomp.exe有用工具创立的文本文件加载到dllHell数据库中。
•DlgDtxt2DB.exe
该有用工具供应Dtxt2DB.exe有用工具的图形用户界面(GUI)版本。
有关DUPS工具的更多信息,请单击上面的文章编号,以检察Microsoft常识库中响应的文章:
247957(http://support.microsoft.com/kb/247957/)示例:利用DUPS.exe办理DLL兼容性成绩
DLL匡助数据库
DLL匡助数据库匡助您查找由Microsoft软件产物安装的特定版本的DLL。有关DLL匡助数据库的更多信息,请会见上面的Microsoft网站:
http://support.microsoft.com/dllhelp/(http://support.microsoft.com/dllhelp/)
DLL开辟
本节先容您在开辟本人的DLL时应当思索的成绩和请求。
DLL的范例
当您在使用程序中加载DLL时,可使用两种链接办法来挪用导出的DLL函数。这两种链接办法是加载时静态链接和运转时静态链接。
加载时静态链接
在加载时静态链接中,使用程序像挪用当地函数一样对导出的DLL函数举行显式挪用。要利用加载时静态链接,请在编译和链策应用程序时供应头文件(.h)和导进库文件(.lib)。当您如许做时,链接器将向体系供应加载DLL所需的信息,并在加载时剖析导出的DLL函数的地位。
运转时静态链接
在运转时静态链接中,使用程序挪用LoadLibrary函数或LoadLibraryEx函数以在运转时加载DLL。乐成加载DLL后,可使用GetProcAddress函数取得要挪用的导出的DLL函数的地点。在利用运转时静态链接时,无需利用导进库文件。
上面的列表申明了有关什么时候利用加载时静态链接和什么时候利用运转时静态链接的使用程序前提:•启动功能
假如使用程序的初始启动功能很主要,则应利用运转时静态链接。
•易用性
在加载时静态链接中,导出的DLL函数相似于当地函数。这使您能够便利地挪用这些函数。
•使用程序逻辑
在运转时静态链接中,使用程序能够分支,以便依照必要加载分歧的模块。在开辟多言语版本时,这一点很主要。
DLL出口点
在创立DLL时,能够有选择地指定出口点函数。当历程或线程将它们本身附加到DLL大概将它们本身从DLL分别时,将挪用出口点函数。您可使用出口点函数依据DLL的必要来初始化数据布局大概烧毁数据布局。别的,假如使用程序是多线程的,则能够在出口点函数中利用线程当地存储(TLS)来分派各个线程公用的内存。上面的代码是一个DLL出口点函数的示例。
<P> BOOLAPIENTRYDllMain(
HANDLEhModule,//HandletoDLLmodule
DWORDul_reason_for_call,//Reasonforcallingfunction
LPVOIDlpReserved)//Reserved
{
switch(ul_reason_for_call)
{
caseDLL_PROCESS_ATTACHED:
//AprocessisloadingtheDLL.
break;
caseDLL_THREAD_ATTACHED:
//Aprocessiscreatinganewthread.
break;
caseDLL_THREAD_DETACH:
//Athreadexitsnormally.
break;
caseDLL_PROCESS_DETACH:
//AprocessunloadstheDLL.
break;
}
returnTRUE;
}
当出口点函数前往FALSE值时,假如您利用的是加载时静态链接,则使用程序不启动。假如您利用的是运转时静态链接,则只要一般DLL不会加载。
出口点函数只应实行复杂的初始化义务,不该挪用任何其他DLL加载函数或停止函数。比方,在出口点函数中,不该间接或直接挪用LoadLibrary函数或LoadLibraryEx函数。别的,不该在历程停止时挪用FreeLibrary函数。
注重:在多线程使用程序中,请确保将对DLL全局数据的会见举行同步(线程平安),以免大概的数据破坏。为此,请利用TLS为各个线程供应独一的数据。
导出DLL函数
要导出DLL函数,您能够导游出的DLL函数中增加函数关头字,也能够创立模块界说文件(.def)以列出导出的DLL函数。
要利用函数关头字,您必需利用以下关头字来声明要导出的各个函数:
__declspec(dllexport)
要在使用程序中利用导出的DLL函数,您必需利用以下关头字来声明要导进的各个函数:
__declspec(dllimport)
一般情形下,您最好利用一个包括define语句和ifdef语句的头文件,以便分开导出语句和导进语句。
您还可使用模块界说文件来声明导出的DLL函数。当您利用模块界说文件时,您不用导游出的DLL函数中增加函数关头字。在模块界说文件中,您能够声明DLL的LIBRARY语句和EXPORTS语句。上面的代码是一个界说文件的示例。
//SampleDLL.def
//
<P> LIBRARY"sampleDLL"
EXPORTS
HelloWorld
示例DLL和使用程序
在MicrosoftVisualC++6.0中,能够经由过程选择“Win32静态链接库”项目范例或“MFC使用程序导游(dll)”来创立DLL。
上面的代码是一个在VisualC++中经由过程利用“Win32静态链接库”项目范例创立的DLL的示例。
//SampleDLL.cpp
//
#include"stdafx.h"
#defineEXPORTING_DLL
#include"sampleDLL.h"
BOOLAPIENTRYDllMain(HANDLEhModule,
DWORDul_reason_for_call,
LPVOIDlpReserved
)
{
returnTRUE;
}
voidHelloWorld()
{
MessageBox(NULL,TEXT("HelloWorld"),TEXT("InaDLL"),MB_OK);
}
//File:SampleDLL.h
//
#ifndefINDLL_H
#defineINDLL_H
#ifdefEXPORTING_DLL
extern__declspec(dllexport)voidHelloWorld();
#else
extern__declspec(dllimport)voidHelloWorld();
#endif
#endif
上面的代码是一个“Win32使用程序”项目标示例,该示例挪用SampleDLLDLL中的导出DLL函数。
//SampleApp.cpp
//
<P> #include"stdafx.h"
#include"sampleDLL.h"
intAPIENTRYWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPSTRlpCmdLine,
intnCmdShow)
{
HelloWorld();
return0;
}
注重:在加载时静态链接中,您必需链接在天生SampleDLL项目时创立的SampleDLL.lib导进库。
在运转时静态链接中,您应利用与以下代码相似的代码来挪用SampleDLL.dll导出DLL函数。
<P> ...
typedefVOID(*DLLPROC)(LPTSTR);
...
HINSTANCEhinstDLL;
DLLPROCHelloWorld;
BOOLfFreeDLL;
hinstDLL=LoadLibrary("sampleDLL.dll");
if(hinstDLL!=NULL)
{
HelloWorld=(DLLPROC)GetProcAddress(hinstDLL,"HelloWorld");
if(HelloWorld!=NULL)
(HelloWorld);
fFreeDLL=FreeLibrary(hinstDLL);
}
...
当您编译和链接SampleDLL使用程序时,Windows操纵体系将依照以下按次鄙人各位置中搜刮SampleDLLDLL:1.使用程叙文件夹
2.以后文件夹
3.Windows体系文件夹
注重:GetSystemDirectory函数前往Windows体系文件夹的路径。
4.Windows文件夹
注重:GetWindowsDirectory函数前往Windows文件夹的路径。
.NETFramework程序集
在引进Microsoft.NET和.NETFramework今后,年夜多半与DLL相干联的成绩已经由过程利用程序集打消了。程序集是在.NET大众言语运转库(CLR)把持之下运转的逻辑功效单位。程序集实践上是作为.dll文件或.exe文件存在的。可是,在外部,程序集与MicrosoftWin32DLL年夜不不异。
程序集文件包括程序集清单、范例元数据、Microsoft两头言语(MSIL)代码和其他资本。程序集清单包括程序集元数据,以供应使程序集成为自形貌程序集所需的全体信息。程序集清单中包括以下信息:•程序集称号
•版本信息
•地区性信息
•强称号信息
•程序集文件列表
•范例援用信息
•援用和依附程序集信息
程序会合包括的MSIL代码是没法间接实行的,必要经由过程CLR来实行。默许情形下,当您创立一个程序集时,该程序集是使用程序专有的。要创立共享程序集,必要为该程序集分派强称号,然后在全局程序集缓存中公布该程序集。
下表申明了程序集的一些功效,并将其与Win32DLL的功效举行了对照:•自形貌
当您创立程序集时,CLR运转该程序集所需的全体信息都包括在程序集清单中。程序集清单包括一个依附程序集列表。因而,CLR能够保护一组在使用程序中利用的分歧的程序集。在Win32DLL中,当您利用共享DLL时,没法保护使用程序中利用的一组DLL之间的分歧性。
•版本把持
在程序集清单中,版本信息由CLR纪录和实行。别的,能够经由过程版本战略来实行版本特定用法。在Win32DLL中,没法由操纵体系实行版本把持。相反,您必需确保DLL向后兼容。
•并行部署
程序集撑持并行部署。一个使用程序可使用一个版本的程序集,而另外一个使用程序可使用另外一分歧版本的程序集。从Windows2000入手下手,经由过程将DLL安排到使用程叙文件夹中撑持并行部署。别的,Windows文件回护可以避免体系DLL被未经受权的代办署理改写或交换。
•自力和断绝
经由过程利用程序集开辟的使用程序能够是自力的,而且与盘算机中正在运转的其他使用程序断绝。这一特征有助于创立零搅扰安装。
•实行
程序集在程序集清单所供应的而且由CLR把持的平安权限下运转。
•言语有关性
能够经由过程利用任何一种受撑持的.NET言语来开辟程序集。比方,能够在MicrosoftVisualC#中开辟程序集,然后在MicrosoftVisualBasic.NET项目中利用该程序集。
参考
有关DLL和.NETFramework程序集的更多信息,请会见上面的Microsoft网站:
DLL匡助数据库
http://support.microsoft.com/dllhelp(http://support.microsoft.com/dllhelp)
DLL抵触(DLLconflicts)
http://msdn.microsoft.com/library/en-us/dnsetup/html/dlldanger1.asp(http://msdn.microsoft.com/library/en-us/dnsetup/html/dlldanger1.asp)
在使用程序中完成并行组件共享(Implementingside-by-sidecomponentsharinginapplications)
http://msdn.microsoft.com/library/en-us/dnsetup/html/sidebyside.asp(http://msdn.microsoft.com/library/en-us/dnsetup/html/sidebyside.asp)
怎样天生和保护用于WindowsXP的自力使用程序和并路程序集(Howtobuildandserviceisolatedapplicationsandside-by-sideassembliesforWindowsXP)
http://msdn.microsoft.com/library/en-us/dnwxp/html/sidexsidewinxp.asp(http://msdn.microsoft.com/library/en-us/dnwxp/html/sidexsidewinxp.asp)
利用.NETFramework简化部署息争决DLL抵触(SimplifyingdeploymentandsolvingDLLconflictswiththe.NETFramework)
http://msdn.microsoft.com/library/en-us/dndotnet/html/dplywithnet.asp(http://msdn.microsoft.com/library/en-us/dndotnet/html/dplywithnet.asp)
.NETFramework开辟职员指南:程序集
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconassemblies.asp(http://msdn.microsoft.com/library/en-us/cpguide/html/cpconassemblies.asp)
创立Win32DL(CreatingaWin32DLL)
http://msdn.microsoft.com/library/en-us/vccore98/html/_core_overview.3a_.creating_a_win32_dll.asp(http://msdn.microsoft.com/library/en-us/vccore98/html/_core_overview.3a_.creating_a_win32_dll.asp)
运转时静态链接
http://msdn2.microsoft.com/en-us/library/ms685090.aspx(http://msdn2.microsoft.com/en-us/library/ms685090.aspx)
线程当地存储(Threadlocalstorage)
http://msdn2.microsoft.com/en-us/library/ms686749.aspx
前几天同学问我学习方向的问题。有点想法,不知道对不对,怕误导同学,现在“开源一下”。注:括号内是我现在整理的时填加上的。 |
|