为啥 LIB 文件具有这种双重性质?
Posted
技术标签:
【中文标题】为啥 LIB 文件具有这种双重性质?【英文标题】:Why are LIB files beasts of such a duplicitous nature?为什么 LIB 文件具有这种双重性质? 【发布时间】:2011-09-19 06:50:42 【问题描述】:我正在尝试了解 Microsoft Windows 上的这个 LIB 文件业务,并且我刚刚发现了一个 - 我希望 - 消除了迄今为止阻止我清楚地了解这个问题的困惑。也就是说,LIB 文件并不是其文件扩展名所暗示的那种文件。
:: cd "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib"
:: lib /nologo /list Ad1.Lib
obj\i386\activdbgid.obj
obj\i386\activscpid.obj
obj\i386\ad1exid.obj
obj\i386\dbgpropid.obj
obj\i386\dispexid.obj
:: lib /nologo /list oledb.lib
o:\winmain.obj.x86fre\enduser\…\oledb\uuid\objfre\i386\oledbiid.obj
o:\winmain.obj.x86fre\enduser\…\oledb\uuid\objfre\i386\oledbnewiid.obj
o:\winmain.obj.x86fre\enduser\…\oledb\uuid\objfre\i386\cmdtreeiid.obj
o:\winmain.obj.x86fre\enduser\…\oledb\uuid\objfre\i386\oledbdepiid.obj
:: lib /nologo /list AdvAPI32.Lib | sort | uniq -c
731 ADVAPI32.dll
前两个示例包含目标文件(在lib.exe
实用程序显示时显示为相对或绝对路径)。然而,第三个示例仅包含对 DLL 的 731 个引用。 (我猜lib.exe
的设计目的不是为此类文件显示更多有用的信息。)
有些包含目标文件,它们是静态库。其他包含符号,它们是导入库。 (有一个short explanation here。)
因此,静态库似乎等同于 Linux 上的 .a
文件,而 DLL 似乎映射到 Linux 上的 .so
文件。 (顺便说一句,导入库如何适应这个 Windows/Linux 等价图?)
现在我想知道为什么会这样?为什么微软决定为导入库提供与静态库相同的文件扩展名? (我知道从历史上看,静态库是最先出现的,就像原始生命形式先于更复杂的形式一样。)他们为什么不说,好吧,这是这些新类型的库,它们应该被称为导入库,它们应该承担文件扩展名.ILB
(或其他)?
【问题讨论】:
来自CMake FAQ:“在 Windows 中,有两种类型的库,一种是静态库,一种是导入库(不过,这两种库都使用 .lib 扩展名令人困惑)。”所以我不是唯一一个对此感到困惑的人。 顺便说一句,MinGW/GCC supports linking directly against the DLL:“ld 的 cygwin/mingw 端口支持直接链接,包括数据符号,到 dll 而不使用任何导入库。这更快,使用更少与传统的导入库方法相比,内存比传统的导入库方法更大,尤其是在链接大型库或应用程序时。...直接链接到 dll 不使用除-L' and
-l' 以外的额外命令行开关...有人可能会想知道为什么要导入库根本用不上。原因有以下三个:..."
据我了解,在 windows 上它不像在 linux 上。您总是链接到 .lib。这个 .lib 可以包含库代码,或一个加载 dll 并从那里运行它的存根。因此,从某种意义上说,您总是静态链接一个 .lib。只是动态链接的时候,.lib中只包含stub,而实际的代码存放在dll中。
@Lumi 我也很好奇导入库有什么好处你不知道吗? PS:你用过的lib工具,从哪里可以得到?谢谢。
@WakanTanka,LIB.EXE
is part of Visual Studio。至于导入库的好处,他们实现了动态链接,所以他们完成了这项工作。 :) Stefano Borini 上面的评论以简洁的方式解释了它们是如何工作的。
【参考方案1】:
因为它们是库。为什么要为与他们已经供应商特定的库完全相同的东西发明一个全新的供应商特定扩展?
【讨论】:
嗯,但 DLL 也是库,这并不妨碍 MS 赋予它们专用的.dll
扩展名。但是,我听到你说,它们是不同的野兽。那么,static 库(包含代码)和 import 库(包含指向代码的指针)呢?它们有什么相似之处以至于给它们取相同的名字是可行的?当 Linux 不需要导入库时,为什么需要导入库才能将代码绑定到 DLL?当你已经知道这些东西很久了,也许这些问题看起来很愚蠢,但如果你是新手,我想你有理由怀疑。
这就是我说的,静态和导入库。导入库并不是什么神奇的东西,当然也不是“代码指针”,它们包含调用LoadLibrary
和GetProcAddress
的普通代码来为您加载函数指针。
DLL 和库之间的区别在于,DLL 是完全编译的,可以在运行时被 anything 使用,而库只能由来的链接器使用使用制作它们的编译器(它们是特定于供应商的)并且仅在编译时。
谢谢 - 我明白了!导入库是普通库,重点是静态链接的库,仅包含动态加载 DLL 中实际代码的代码。这在MSDN docs for the cl.exe /MD
option中也有简要说明。以上是关于为啥 LIB 文件具有这种双重性质?的主要内容,如果未能解决你的问题,请参考以下文章