dll文件介绍
比较大【bǐ jiào dà】的【de】🚄应用程序【chéng xù】都🤛由很多模块组成,这些模块分别🕳完成相【wán chéng xiàng】🖐对独立的功能【de gōng néng】,它们彼🏊此协作【cǐ xié zuò】来完成整个软件系统🍢的【de】工作。可能存🦈在一些🎆模块的【mó kuài de】功能较📕为通用🦅,在构造【zài gòu zào】其它软件系统🍢时仍会被使用【bèi shǐ yòng】。在构造【zài gòu zào】软件系统🍢时,如果将所有模块的【mó kuài de】源代码【dài mǎ】📆都静态编译到【biān yì dào】整🔑个应用【gè yīng yòng】程序【chéng xù】🦏 EXE 文件中🎂,会产生【huì chǎn shēng】一些问【yī xiē wèn】题【tí】🥪:一个缺💽点是【diǎn shì】增加了应用程序【chéng xù】🦏的【de】大小,它会占🔀用更多【yòng gèng duō】🦄的【de】磁盘空间【jiān】🥪,程序【chéng xù】运㊙行时也会消耗【huì xiāo hào】较大的【jiào dà de】🚄内存空间【jiān】🥪,造成系统资源【tǒng zī yuán】的【de】浪费;另一个缺💽点是【diǎn shì】,在编写大的【de】🚄 EXE 程序【chéng xù】🦏时,在每次【zài měi cì】⛩修改重🏦建时都必须调【bì xū diào】整编译所有源【suǒ yǒu yuán】代码【dài mǎ】📆,增加了编译过程的【de】复🌲杂性【zá xìng】,也不利于阶段性的【de】单♎元测试【yuán cè shì】。
Windows 系统平【xì tǒng píng】🔭台上提供了一📞种完全不同的【bú tóng de】🎉较有效的编程和运行【hé yùn háng】⚓环境👕,你可以【nǐ kě yǐ】🌚将独立【jiāng dú lì】的程序模块创建为较🤮小的 DLL (Dynamic Linkable Library) 文件【wén jiàn】,并可对它们单🏆独编译和测试。在运行时,只有当 EXE 程序确👕实要调用这些【zhè xiē】 DLL 模块的【mó kuài de】情况下,系统才✌会将它【huì jiāng tā】们装载到内存🍛空间中。这种方式不仅减少了 EXE 文件的【wén jiàn de】大小和对内存【duì nèi cún】空间的【kōng jiān de】需求【xū qiú】👩,而且使♌这些【zhè xiē】 DLL 模块可以同时🆓被多个应用程序使用😑。Windows 自己就【zì jǐ jiù】将一些🤘主要的系统功能以【néng yǐ】 DLL 模块的【mó kuài de】形式实【xíng shì shí】现【xiàn】🍏。
一般来说,DLL 是一种【shì yī zhǒng】磁盘文件🎧,以【yǐ】.dll、.DRV、.FON、.SYS 和许多以【yǐ】 .EXE 为扩展🚞名的系统文件🏰都可以【yǐ】⛱是【shì】 DLL。它由全局数据【jú shù jù】、服务函🥂数和资源组成,在运行时被系统加载到调用进程【yòng jìn chéng】的🏕虚拟空【xū nǐ kōng】间中,成为调【chéng wéi diào】用进程【yòng jìn chéng】的🏕一部分。如果与🥩其它🎆 DLL 之间没🌐有冲突,该文件【gāi wén jiàn】🎧通常映【tōng cháng yìng】⛹射到进程虚拟空【xū nǐ kōng】间的同一地址上【zhǐ shàng】。DLL 模块中包含各【bāo hán gè】种导出函数,用于向🌸外界提🚖供服务。DLL 可以有【kě yǐ yǒu】⛪自己的【zì jǐ de】数据段,但没有【dàn méi yǒu】⬛自己的【zì jǐ de】堆栈🔢,使用与😪调用它的应用程序相【chéng xù xiàng】🥖同的堆🌮栈模式;一个【yī gè】 DLL 在内存中只有📂一个【yī gè】实🙂例【lì】;DLL 实现了代码封装性【zhuāng xìng】;DLL 的编制与具体【yǔ jù tǐ】的编程【de biān chéng】语言及🌳编译器【biān yì qì】无关【wú guān】。
在🤖 Win32 环境中,每个进程都复制了自【zhì le zì】己的读/写全局🔽变量【liàng】。如果想😃要与其🐂它进程【tā jìn chéng】共享内存🛄,必须使【bì xū shǐ】🗾用内存🛄映射文件或者【jiàn huò zhě】声明一个共享数据段🎈。DLL 模块需要的堆栈内存【zhàn nèi cún】🍨都是从运行进🍟程的堆【chéng de duī】栈中分配🔥出来的【chū lái de】。Windows 在🤖加载 DLL 模块时将进程【jiāng jìn chéng】函数调【hán shù diào】用与 DLL 文件的💲导出函数相匹【shù xiàng pǐ】配🔥。Windows 操作系统对 DLL 的操作【de cāo zuò】🚮仅仅是【jǐn jǐn shì】把 DLL 映射到🥑需要它【xū yào tā】的进程的虚拟【de xū nǐ】地址空间里去✂。DLL 函数中【hán shù zhōng】🤽的代码所创建【suǒ chuàng jiàn】🙆的任何对象📼(包括变量【liàng】)都归调用它的【yòng tā de】💠线程或🐂进程所【jìn chéng suǒ】有。
调用方式
1、静态调用【yòng】⛷方式:由编译系统完🚀成对【duì】🧥 DLL 的加载和应用【hé yīng yòng】⛷程序结束时💊 DLL 卸载的👮编码(如还有【rú hái yǒu】其它程🐄序使用【yòng】🌅该【gāi】 DLL,则 Windows 对【duì】 DLL 的应用【yòng】⛷记录减1,直到所有相关程序都【chéng xù dōu】结束对【duì】该【gāi】 DLL 的使用【de shǐ yòng】⛷时才释【shí cái shì】放它🦌,简单实用【yòng】⛷,但不够灵活👕,只能满足一般【zú yī bān】📙要求【yào qiú】👦。
隐式的【de】🌔调用【diào yòng】:需要把产生动✋态连接🤟库时【shí】产生的【de】 .LIB 文件加【wén jiàn jiā】入到应用程【yīng yòng chéng】序【xù】🕣的【de】工程中【zhōng】😻,想使用 DLL 中【zhōng】😻的【de】函数时【shí】,只须说👬明一下。隐式调用【diào yòng】不需📯要调用【yào diào yòng】📩 LoadLibrary() 和 FreeLibrary()。程序【xù】员🍊在建立【zài jiàn lì】🍷一个 DLL 文件时【wén jiàn shí】,链接程【liàn jiē chéng】序【xù】会自💔动生成【dòng shēng chéng】⛑一个与之对应【zhī duì yīng】的【de】 LIB 导入文件。该文件【gāi wén jiàn】🚆包含了每一个 DLL 导出函数的【de】符号名和📸可选的【kě xuǎn de】标识号,但是并不含有🆙实际的【de】🍧代码。LIB 文件作为 DLL 的替代【de tì dài】文件被编译到【biān yì dào】应用程【yīng yòng chéng】序【xù】🕣项目中【zhōng】😻。
当程序📑员通过【yuán tōng guò】静态链🐺接方式👆编译生【biān yì shēng】成应用【chéng yīng yòng】程序时,应用程序中的【xù zhōng de】调用函数与🔑 LIB 文件中【wén jiàn zhōng】🏄导出符🚨号相匹【hào xiàng pǐ】配,这些符【zhè xiē fú】号或标🗃识号进🤫入到生成的【de】 EXE 文件中【wén jiàn zhōng】🏄。LIB 文件中【wén jiàn zhōng】🏄也包含😱了对应的【de】 DL L文件名(但不是【dàn bú shì】完全的【de】💶路径名),链接程序将其【xù jiāng qí】存储在🌟 EXE 文件内【wén jiàn nèi】部。
当应用程【yīng yòng chéng】序运👹行过程【háng guò chéng】🗽中需要【zhōng xū yào】😋加载【jiā zǎi】🚣 DLL 文件时,Windows 根据这些信息发现并加载【jiā zǎi】🚣 DLL,然后通过符号【guò fú hào】名或标【míng huò biāo】🖲识号实【shí hào shí】现对 DLL 函数的🌤动态链【dòng tài liàn】接【jiē】🚺。所有被应用程【yīng yòng chéng】序调用【diào yòng】🔗的🌤 DLL 文件都会在应【huì zài yīng】用程序 EXE 文件加载【jiā zǎi】🚣时被加载【jiā zǎi】在🤽到内存中。可执行😄程序链🕹接【jiē】🚺到一个包含 DLL 输出函【shū chū hán】数信息👔的输入😉库文件(.LIB文件)。操作系【cāo zuò xì】统在加【tǒng zài jiā】🤬载使用【zǎi shǐ yòng】可执行😄程序时加载【jiā zǎi】🚣 DLL。可执行😄程序直接【jiē】🚺通过函数名【shù míng】🥊调用【diào yòng】🔗 DLL 的🌤输出函【shū chū hán】数,调用【diào yòng】🔗方法和【fāng fǎ hé】程序内【chéng xù nèi】部😰其 它的【tā de】🌤函数是一样的🌤。
2、动态调【dòng tài diào】🌅用方式【yòng fāng shì】:是由编程者用 API 函数加🌈载和卸【zǎi hé xiè】🐓载 DLL 来达到调用 DLL 的目的,使用上【shǐ yòng shàng】🗽较复杂,但能更【dàn néng gèng】加有效【jiā yǒu xiào】地使用👦内存【nèi cún】,是编制🐦大型应✉用程序时的重要方式。
显式的【xiǎn shì de】⏫调用【yòng】🔃:是指在【shì zhǐ zài】应用【yīng yòng】🔃程序中用【yòng】🔃 LoadLibrary 或【huò】 MFC 提供的【tí gòng de】💄 AfxLoadLibrary 显式的【xiǎn shì de】⏫将自己【jiāng zì jǐ】🧕所做的【suǒ zuò de】⏫动态连【dòng tài lián】接库调【jiē kù diào】进来【jìn lái】⏫,动态连【dòng tài lián】接库的【de】⏫文件名🌀即是上【jí shì shàng】👃面两个【miàn liǎng gè】⛅函数【hán shù】🔬的【de】⏫参数【cān shù】🍇,再用【zài yòng】🕸 GetProcAddress() 获取想【huò qǔ xiǎng】要引入的【de】⏫函数【hán shù】🔬。自此📩,你就可【nǐ jiù kě】以象使🗄用【yòng】如同🍣本应用【yīng yòng】🔃程序自【chéng xù zì】定【dìng】义的【de】🍬函数【hán shù】🔬一样来调👽用【yòng】🔃此引入函数【hán shù】🔬了。在应用【yīng yòng】🔃程序退🛴出之前【zhī qián】🆚,应该用【yīng gāi yòng】🔃 FreeLibrary 或【huò】 MFC 提供的【tí gòng de】💄 AfxFreeLibrary 释放动【shì fàng dòng】态连接库。直接调用【yòng】🔃 Win32 的【de】⏫ LoadLibary 函数【hán shù】🔬,并指定【dìng】 DLL 的【de】⏫路径作为👽参数【cān shù】🍇。LoadLibary 返回 HINSTANCE 参数【cān shù】🍇,应用【yīng yòng】🔃程序在调🌸用【yòng】🔃 GetProcAddress 函数【hán shù】时🥈使用【shǐ yòng】🔃这一参数【cān shù】🍇。GetProcAddress 函数【hán shù】🔬将符号名或【huò】标识号转换为【huàn wéi】👽 DLL 内部的【nèi bù de】⏫地址。程序员可以决定【dìng】 DLL 文件何时加载【zǎi】或【huò】不加➰载【zǎi】,显式链接在运🐘行时决定【dìng】加载【zǎi】哪个😀 DLL 文件。使用【shǐ yòng】🔃 DLL 的【de】⏫程序在使用【shǐ yòng】🔃之前必【zhī qián bì】🏭须加载【zǎi】(LoadLibrary)加载【zǎi】DLL从而得到一个🎧DLL模块的【de】🛒句柄,然后调用【yòng】🔃 GetProcAddress 函数【hán shù】🔬得到输【dé dào shū】出函数【hán shù】🔬的【de】⏫指针,在退出之前【zhī qián】🆚必须卸载【zǎi】💁DLL(FreeLibrary)。
Windows将遵循【jiāng zūn xún】下面的搜索顺【sōu suǒ shùn】🛳序来定🏧位 DLL:
- 包含EXE文件的目录
- 进程的当前工作目录
- Windows系统目录
- Windows目录
- 列在 Path 环境变量中的一系列目录
MFC中的DLL
- Non-MFC DLL:指的是不用✖ MFC 的类库【de lèi kù】结构⏮,直接用✖ C 语言写的 DLL,其输出的函数一般用【yī bān yòng】😥的是标【de shì biāo】准 C 接口【jiē kǒu】🎪,并能被 非💴 MFC 或【huò】🌐 MFC 编写的应用【yīng yòng】✖程序所调用✖。
- Regular DLL:和下述🕠的【de】🤚 Extension DLLs 一样🤮,是用【shì yòng】🐰 MFC 类库编【lèi kù biān】写的【de】😢。明显的【de】📯特点是🔁在源文🈳件里有一个🐈继承【jì chéng】 CWinApp 的【de】🤚类。其又可【qí yòu kě】细分成静态【tài】📚连接到【lián jiē dào】👼 MFC 和动态【hé dòng tài】📚连接到【lián jiē dào】👼 MFC 上的【shàng de】🤚。
静态【tài】📚连接到【lián jiē dào】👼 MFC 的【de】动态【dòng tài】🥩连接库只被 VC 的【de】🤚专业 版和企业版所🚯支持。该类 DLL 应用【yīng yòng】🐰程序里【chéng xù lǐ】头的【de】输出【chū】😖函数可【hán shù kě】以被任【yǐ bèi rèn】🥘意🎰 Win32 程序使🎟用【yòng】🐰,包括使用【yòng】🐰 MFC 的【de】应用【yīng yòng】💺程序。输入函【shū rù hán】数有如下形式:
extern "C" EXPORT YourExportedFunction();
如果没有 extern "C" 修饰🔦,输出【chū】函数仅仅能从【cóng】 C++ 代码中【zhōng】调用【diào yòng】🐰。
DLL 应用【yīng yòng】🐰程序从【chéng xù cóng】🚇 CWinApp 派生【pài shēng】🏙,但没有🤓消息循【xiāo xī xún】环🌹。
动态【dòng tài】链👰接到👼 MFC 的【de】🤚 规则【guī zé】 DLL 应用【yīng yòng】🐰程序里【chéng xù lǐ】头的【de】输出【chū】😖函数可【hán shù kě】以被任【yǐ bèi rèn】🥘意🎰 Win32 程序使🎟用【yòng】🐰,包括使用【yòng】🐰 MFC 的【de】应用【yīng yòng】💺程序。但是,所有从【suǒ yǒu cóng】 DLL 输出【chū】的【de】🤚函数应【hán shù yīng】🕊该以如下语句【xià yǔ jù】🤾开始:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
此语句用【yòng】🐰来正确地切换 MFC 模块状态【tài】📚。
Regular DLL能够被所有支持 DLL 技术的【jì shù de】🚡语言所【yǔ yán suǒ】编写的【de】😢应用【yīng yòng】🐰程序所调用【diào yòng】🐰。在这种【zài zhè zhǒng】🌓动态【dòng tài】📚连接库中【zhōng】,它必须有一个🐈从【cóng】 CWinApp 继承下【jì chéng xià】🤲来的【de】类🥑,DLLMain 函数被【hán shù bèi】😸 MFC 所提供【suǒ tí gòng】👒,不用【yòng】🐰自己显式的【shì de】🤚写出来【xiě chū lái】。
-
Extension DLL:用来实现从【xiàn cóng】 MFC 所继承【suǒ jì chéng】🍴下来的【de】😘类的重【lèi de chóng】😧新利用,也就是🎮说,用这种类型的【lèi xíng de】⛪动态连【dòng tài lián】接库,可以用【kě yǐ yòng】来输出【lái shū chū】🥎一个从【cóng】 MFC 所继承【suǒ jì chéng】🍴下来的【de】😘类【lèi】。它输出的【de】⛪函数【hán shù】⛓仅可以被使用【shǐ yòng】🏺 MFC 且动态【qiě dòng tài】链接到👓 MFC 的【de】⛪应用程🤕序使用【xù shǐ yòng】。可以从【cóng】 MFC 继承你🎽所想要【suǒ xiǎng yào】➖的【de】⛪、更适于🚘你自己用的【de】⛪类【lèi】,并把它【bìng bǎ tā】👴提供给你的【de】应🔎用程序【yòng chéng xù】。你也可随意的【de】🕥给你的【de】应🔎用程序【yòng chéng xù】提供 MFC 或💟 MFC 继承类【lèi】的【de】⛪对象【duì xiàng】指针。Extension DLL使用【shǐ yòng】 MFC 的【de】⛪动态连【dòng tài lián】接版本所创建的【de】🚠,并且它【bìng qiě tā】只被用【zhī bèi yòng】🈁 MFC 类【lèi】库所编写的【biān xiě de】⛪应用程🤕序所调用🏼。Extension DLLs 和【hé】 Regular DLLs 不一样【bú yī yàng】,它没有【tā méi yǒu】🚀从【cóng】 CWinApp 继承而来的【de】⛪类【lèi】的【de】⛪对象【duì xiàng】,所以📞,你必须为自己 DLLMain 函数【hán shù】⛓添加初始化代【shǐ huà dài】码🥓和【hé】结束代码【dài mǎ】🐈。
和【hé】规则📎 DLL 相比【xiàng bǐ】,有以下不同🅿:
1、它没有【tā méi yǒu】🚀从【cóng】 CWinApp 派生的【de】⛪对象【duì xiàng】;
2、它必须有一个 DLLMain 函数【hán shù】⛓;
3、DLLMain 调用🏼 AfxInitExtensionModule 函数【hán shù】⛓,必须检🏅查该函数【hán shù】⛓的【de】⛪返回【huí】值🥩,如果返回【huí】0,DLLMmain 也返回【huí】 0;
-
4、如果它【rú guǒ tā】😚希望输【xī wàng shū】⛑出【chū】 CRuntimeClass 类型的对象或者资源,则需要提供一个初始化函数🥂来创建【lái chuàng jiàn】🎣一个 CDynLinkLibrary 对象。并且【bìng qiě】,有必要【yǒu bì yào】把初始🏸化函数🥂输出【chū】;
5、使用扩展【kuò zhǎn】🆑 DLL 的 MFC 应用程序必须有一个从👔 CWinApp 派生的类🎣,而且,一般在【yī bān zài】InitInstance 里调用【lǐ diào yòng】🥔扩展【kuò zhǎn】🆑 DLL 的初始【de chū shǐ】化函数【huà hán shù】🍪。
DLL入口函数
1、每一个【měi yī gè】 DLL 必须有【bì xū yǒu】♍一个入【yī gè rù】口点😩,DLLMain 是一个【shì yī gè】🐞缺省的【quē shěng de】入口函数🆕。DLLMain 负责初【fù zé chū】😽始化和结束工作,每当一【měi dāng yī】个新的💷进程或者✈该进程的新的线程【xiàn chéng】访问💯 DLL 时,或者访问💯 DLL 的每一个【měi yī gè】进程或者✈线程【xiàn chéng】不再使用【shǐ yòng】🏭DLL或者结【huò zhě jié】束时【shù shí】🏔,都会调❄用🏭 DLLMain。但是,使用【shǐ yòng】🏭 TerminateProcess 或 TerminateThread 结束进程或者✈线程【xiàn chéng】,不会调🔏用🏭 DLLMain。
DLLMain的函数原型:
BOOL APIENTRY DLLMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID
lpReserved)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
.......
case DLL_THREAD_ATTACH:
.......
case DLL_THREAD_DETACH:
.......
case DLL_PROCESS_DETACH:
.......
return TRUE;
}
}参数:
hMoudle:是动态💈库被调用时所传递来💥的一个🏫指向【xiàng】自己的句【jǐ de jù】柄【bǐng】(实际上🧡,它是指向【xiàng】_DGROUP段的一【duàn de yī】🌛个选择符【fú】);
ul_reason_for_call:是一个👳说明动【shuō míng dòng】态库被调原因【diào yuán yīn】的标志🌇。当进程🧑或线程🛑装入或卸载动态连接【tài lián jiē】库的时【kù de shí】
关键词:dll,dll文件
阅读本文后您有什么感想? 已有 人给出评价!
- 0
- 0
- 0
- 0
- 0
- 0