动态链接库Word下载.docx
- 文档编号:20194196
- 上传时间:2023-01-17
- 格式:DOCX
- 页数:45
- 大小:37.39KB
动态链接库Word下载.docx
《动态链接库Word下载.docx》由会员分享,可在线阅读,更多相关《动态链接库Word下载.docx(45页珍藏版)》请在冰豆网上搜索。
例如,假设要为Windows编写一个由几个不同的程序组成的大型财务软件包,就会发现这些应用程序会使用许多共同的例程。
可以把这些公共例程放入一个一般性的目的码链接库(带.LIB扩展名)中,并在使用LINK静态连结时把它们加入各程序模块中。
但这种方法是很浪费的,因为软件包中的每个程序都包含与公共例程相同的程序代码。
而且,如果修改了链接库中的某个例程,就要重新连结使用此例程的所有程序。
然而,如果把这些公共例程放到称为ACCOUNT.DLL的动态链接库中,就可解决这两个问题。
只有动态链接库模块才包含所有程序都要用到的例程。
这样能为储存文件节省磁盘空间,并且在同时执行多个应用程序时节省内存,而且,可以修改动态链接库模块而不用重新连结各个程序。
动态链接库实际上是可以独立存在的。
例如,假设您编写了一系列3D绘图例程,并把它们放入名为GDI3.DLL的DLL中。
如果其它软件开发者对此链接库很感兴趣,您就可以授权他们将其加入他们的图形程序中。
使用多个这样的图形程序的使用者只需要一个GDI3.DLL文件。
链接库:
一词多义
动态链接库有着令人困惑的印象,部分原因是由于「链接库」这个词被放在几种不同的用语之后。
除了动态链接库之外,我们也用它来称呼「目的码链接库」或「引用链接库」。
目的码链接库是带.LIB扩展名的文件。
在使用连结程序进行静态连结时,它的程序代码就会加到程序的.EXE文件中。
例如,在MicrosoftVisualC++中,连同程序连结的一般C执行目的码链接库被称为LIBC.LIB。
引用链接库是目的码链接库文件的一种特殊形式。
像目的码链接库一样,引用链接库有.LIB扩展名,并且被连结器用来确定程序代码中的函数呼叫来源。
但引用链接库不含程序代码,而是为连结程序提供信息,以便在.EXE文件中建立动态链接时要用到的复位位表。
包含在Microsoft编译器中的KERNEL32.LIB、USER32.LIB和GDI32.LIB文件是Windows函数的引用链接库。
如果一个程序呼叫Rectangle函数,Rectangle将告诉LINK,该函数在GDI32.DLL动态链接库中。
该信息被记录在.EXE文件中,使得程序执行时,Windows能够和GDI32.DLL动态链接库进行动态连结。
目的码链接库和引用链接库只用在程序开发期间使用,而动态链接库在执行期间使用。
当一个使用动态链接库的程序执行时,该动态链接库必须在磁盘上。
当Windows要执行一个使用了动态链接库的程序而需要加载该链接库时,动态链接库文件必须储存在含有该.EXE程序的目录下、目前的目录下、Windows系统目录下、Windows目录下,或者是在通过MS-DOS环境中的PATH可以存取到的目录下(Windows会按顺序搜索这些目录)。
一个简单的DLL
虽然动态链接库的整体概念是它们可以被多个应用程序所使用,但您通常最初设计的动态链接库只与一个应用程序相联系,可能是一个「测试」程序在使用DLL。
下面就是我们要做的。
我们建立一个名为EDRLIB.DLL的DLL。
文件名中的「EDR」代表「简便的绘图例程(easydrawingroutines)」。
这里的EDRLIB只含有一个函数(名称为EdrCenterText),但是您还可以将应用程序中其它简单的绘图函数添加进去。
应用程序EDRTEST.EXE将通过呼叫EDRLIB.DLL中的函数来利用它。
要做到这一点,需要与我们以前所做的略有不同的方法,也包括VisualC++中我们没有看过的特性。
在VisualC++中「工作空间(workspaces)」和「项目(projects)」不同。
项目通常与建立的应用程序(.EXE)或者动态链接库(.DLL)相联系。
一个工作空间可以包含一个或多个项目。
迄今为止,我们所有的工作空间都只包含一个项目。
我们现在就建立一个包含两个项目的工作空间EDRTEST-一个用于建立EDRTEST.EXE,而另一个用于建立EDRLIB.DLL,即EDRTEST使用的动态链接库。
现在就开始。
在VisualC++中,从「File」菜单选择「New」,然后选择「Workspaces」页面标签。
(我们以前从来没有选择过。
)在「Location」栏选择工作空间要储存的目录,然后在「WorkspaceName」栏输入「EDRTEST」,按Enter键。
这样就建立了一个空的工作空间。
DeveloperStudio还建立了一个名为EDRTEST的子目录,以及工作空间文件EDRTEST.DSW(就像两个其它文件)。
现在让我们在此工作空间里建立一个项目。
从「File」菜单选择「New」,然后选择「Projects」页面标签。
尽管过去您选择「Win32Application」,但现在「Win32Dynamic-LinkLibrary」。
另外,单击单选按钮「AddToCurrentWorkspace」,这使得此项目是「EDRTEST」工作空间的一部分。
在「ProjectName栏输入EDRLIB,但先不要按「OK」按钮。
当您在ProjectName栏输入EDRLIB时,VisualC++将改变「Location」栏,以显示EDRLIB作为EDRTEST的一个子目录。
这不是我们要的,所以接着在「Location」栏删除EDRLIB子目录以便项目建立在EDRTEST目录。
现在按「OK」。
屏幕将显示一个对话框,询问您建立什么型态的DLL。
选择「AnEmptyDLLProject」,然后按「Finish」。
VisualC++将建立一个项目文件EDRLIB.DSP和一个构造文件EDRLIB.MAK(如果「ToolsOptions」对话框的B「uild页面卷标中选择了「ExportMakefile」选项」。
现在您已经在此项目中添加了一对文件。
从「File」菜单选择「New」,然后选择「Files」页面标签。
选择「C/C++HeaderFile」,然后输入文件名EDRLIB.H。
输入程序21-1所示的文件(或者从本书光盘中复制)。
再次从「File」菜单中选择「New」,然后选择「Files」页面标签。
这次选择「C++SourceFile」,然后输入文件名EDRLIB.C。
继续输入程序21-1所示的程序。
程序21-1EDRLIB动态链接库
EDRLIB.H
/*--------------------------------------------------------------------------
EDRLIB.Hheaderfile
----------------------------------------------------------------------------*/
#ifdef__cplusplus
#defineEXPORTextern"
C"
__declspec(dllexport)
#else
#defineEXPORT__declspec(dllexport)
#endif
EXPORTBOOLCALLBACKEdrCenterTextA(HDC,PRECT,PCSTR);
EXPORTBOOLCALLBACKEdrCenterTextW(HDC,PRECT,PCWSTR);
#ifdefUNICODE
#defineEdrCenterTextEdrCenterTextW
#defineEdrCenterTextEdrCenterTextA
#endif
EDRLIB.C
/*---------------------------------------------------------------------------
EDRLIB.C--EasyDrawingRoutineLibrarymodule
(c)CharlesPetzold,1998
-----------------------------------------------------------------------------*/
#includewindows.h>
#include"
edrlib.h"
intWINAPIDllMain(HINSTANCEhInstance,DWORDfdwReason,PVOIDpvReserved)
{
returnTRUE;
}
EXPORTBOOLCALLBACKEdrCenterTextA(HDChdc,PRECTprc,PCSTRpString)
intiLength;
SIZEsize;
iLength=lstrlenA(pString);
GetTextExtentPoint32A(hdc,pString,iLength,&
size);
returnTextOutA(hdc,(prc->
right-prc->
left-size.cx)/2,(prc->
bottom-prc->
top-size.cy)/2,pString,Length);
}
EXPORTBOOLCALLBACKEdrCenterTextW(HDChdc,PRECTprc,PCWSTRpString)
iLength=lstrlenW(pString);
GetTextExtentPoint32W(hdc,pString,iLength,&
returnTextOutW(hdc,(prc->
left-size.cx)/2,
(prc->
top-size.cy)/2,
pString,iLength);
这里您可以按Release设定,或者也可以按Debug设定来建立EDRLIB.DLL。
之后,RELEASE和DEBUG目录将包含EDRLIB.LIB(即动态链接库的引用链接库)和EDRLIB.DLL(动态链接库本身)。
纵观全书,我们建立的所有程序都可以根据UNICODE标识符来编译成使用Unicode或非Unicode字符串的程序代码。
当您建立一个DLL时,它应该包括处理字符和字符串的Unicode和非Unicode版的所有函数。
因此,EDRLIB.C就包含函数EdrCenterTextA(ANSI版)和EdrCenterTextW(宽字符版)。
EdrCenterTextA定义为带有参数PCSTR(指向const字符串的指针),而EdrCenterTextW则定义为带有参数PCWSTR(指向const宽字符串的指针)。
EdrCenterTextA函数将呼叫lstrlenA、GetTextExtentPoint32A和TextOutA。
EdrCenterTextW将呼叫lstrlenW、GetTextExtentPoint32W和TextOutW。
如果定义了UNICODE标识符,则EDRLIB.H将EdrCenterText定义为EdrCenterTextW,否则定义为EdrCenterTextA。
这样的做法很像Windows表头文件。
EDRLIB.H也包含函数DllMain,取代了DLL中的WinMain。
此函数用于执行初始化和未初始化(deinitialization),我将在下一节讨论。
我们现在所需要的就是从DllMain传回TRUE。
在这两个文件中,最后一点神秘之处就是定义了EXPORT标识符。
DLL中应用程序使用的函数必须是「输出(exported)」的。
这跟税务或者商业制度无关,只是确保函数名添加到EDRLIB.LIB的一个关键词(以便连结程序在连结使用此函数的应用程序时,能够解析出函数名称),而且该函数在EDRLIB.DLL中也是看得到的。
EXPORT标识符包括储存方式限定词__declspec(dllexport)以及在表头文件按C++模式编译时附加的「C」。
这将防止编译器使用C++的名称轧压规则(namemangling)来处理函数名称,使C和C++程序都能使用这个DLL。
链接库入口/出口点
当动态链接库首次启动和结束时,我们呼叫了DllMain函数。
DllMain的第一个参数是链接库的执行实体句柄。
如果您的链接库使用需要执行实体句柄(诸如DialogBox)的资源,那么您应该将hInstance储存为一个整体变量。
DllMain的最后一个参数由系统保留。
fdwReason参数可以是四个值之一,说明为什么Windows要呼叫DllMain函数。
在下面的讨论中,请记住一个程序可以被加载多次,并在Windows下一起执行。
每当一个程序加载时,它都被认为是一个独立的程序(process)。
fdwReason的一个值DLL_PROCESS_ATTACH表示动态链接库被映像到一个程序的地址空间。
链接库可以根据这个线索进行初始化,为以后来自该程序的请求提供服务。
例如,这类初始化可能包括内存配置。
在一个程序的生命周期内,只有一次对DllMain的呼叫以DLL_PROCESS_ATTACH为参数。
使用同一DLL的其它任何程序都将导致另一个使用DLL_PROCESS_ATTACH参数的DllMain呼叫,但这是对新程序的呼叫。
如果初始化成功,DllMain应该传回一个非0值。
传回0将导致Windows不执行该程序。
当fdwReason的值为DLL_PROCESS_DETACH时,意味着程序不再需要DLL了,从而提供给链接库自己清除自己的机会。
在32位的Windows下,这种处理并不是严格必须的,但这是一种良好的程序写作习惯。
类似地,当以DLL_THREAD_ATTACH为fdwReason参数呼叫DllMain时,意味着某个程序建立了一个新的线程。
当线程中止时,Windows以DLL_THREAD_DETACH为fdwReason参数呼叫DllMain。
请注意,如果动态链接库是在线程被建立之后和一个程序连结的,那么可能会得到一个没有事先对应一个DLL_THREAD_ATTACH呼叫的DLL_THREAD_DETACH呼叫。
当使用一个DLL_THREAD_DETACH参数呼叫DllMain时,线程仍然存在。
动态链接库甚至可以在这个程序期间发送线程消息。
但是它不应该使用PostMessage,因为线程可能在此消息被处理到之前就已经退出执行了。
测试程序
现在让我们在EDRTEST工作空间里建立第二个项目,程序名称为EDRTEST,而且使用EDRLIB.DLL。
在VisualC++中加载EDRTEST工作空间时,请从「File」菜单选择「New」,然后在「New」对话框中选择「Projects」页面标签。
这次选择「Win32Application」,并确保选中了「AddToCurrentWorkspace」按钮。
输入项目名称EDRTEST。
再在「Locations」栏删除第二个EDRTEST子目录。
按下「OK」,然后在下一个对话框选择「AnEmptyProject」,按「Finish」。
从「File」菜单再次选择「New」。
选择「Files」页面标签然后选择「C++SourceFile」。
确保「AddToProject」清单方块显示「EDRTEST」而不是「EDRLIB」。
输入文件名称EDRTEST.C,然后输入程序21-2所示的程序。
此程序用EdrCenterText函数将显示区域中的字符串居中对齐。
程序21-2EDRTEST
EDRTEST.C
/*---------------------------------------------------------------------------
EDRTEST.C--ProgramusingEDRLIBdynamic-linklibrary
(c)CharlesPetzold,1998
----------------------------------------------------------------------------*/
#include<
windows.h>
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,PSTRszCmdLine,intiCmdShow)
{
staticTCHARszAppName[]=TEXT("
StrProg"
);
HWNDhwnd;
MSGmsg;
WNDCLASSwndclass;
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;
if(!
RegisterClass(&
wndclass))
{
MessageBox(NULL,TEXT("
ThisprogramrequiresWindowsNT!
"
),
szAppName,MB_ICONERROR);
return0;
}
hwnd=CreateWindow(szAppName,TEXT("
DLLDemonstrationProgram"
),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&
msg,NULL,0,0))
{
TranslateMessage(&
msg);
DispatchMessage(&
returnmsg.wParam;
LRESULTCALLBACKWndProc(HWNDhwnd,UINTmessage,WPARAMwParam,LPARAMlParam)
HDChdc;
PAINTSTRUCTps;
RECTrect;
switch(message)
caseWM_PAINT:
hdc=BeginPaint(hwnd,&
ps);
GetClientRect(hwnd,&
rect);
EdrCenterText(hdc,&
rect,TEXT("
ThisstringwasdisplayedbyaDLL"
));
EndPaint(hwnd,&
caseWM_DESTROY:
PostQuitMessage(0);
}
returnDefWindowProc(hwnd,message,wParam,lParam);
注意,为了定义EdrCenterText函数,EDRTEST.C包括EDRLIB.H表头文件,此函数将在WM_PAINT消息处理期间呼叫。
在编译此程序之前,您可能希望做以下几件事。
首先,在「Project」菜单选择「SelectActiveProject」。
这时您将看到「EDRLIB」和「EDRTEST」,选择「EDRTEST」。
在重新编译此工作空间时,您真正要重新编译的是程序。
另外,在「Project」菜单中,选择「Dependencies」,在「SelectProjectToModify」清单方
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 动态 链接