导入库如何工作以及为什么MinGW不需要它们?

时间:2015-01-07 16:34:53

标签: c++ c windows dll linker

我查看了这个页面:An In-Depth Look into the Win32 Portable Executable File Format

它解释了链接器需要一个导入库,因为编译器无法区分正常函数调用和API函数调用。但他们也说__declspec(dllimport)指定函数调用为API调用,因此链接器链接__imp_[function-name]但是使用此关键字,编译器应该知道这是对API函数的调用。

为什么链接器仍然需要导入库?编译器可以将此符号标记为通过将__imp_添加到函数名称而导入,并且可以调用函数指针(这是一个尚未解析的符号),并且链接器可以替换此符号(因为它看到这是一个API调用)与IAT条目的地址。

为什么MinGW-linker直接使用“MinGW-DLLs”,但Visual-Studio链接器需要导入库?

在我阅读帖子时,还提出了一些其他问题。在完成与最终可执行文件的链接之前,“dlltool(或链接器)”(无论哪个创建导入库)如何知道IAT条目的位置?我认为IAT条目将在链接时与最终可执行文件一起构建。帖子说,每个API-Call在IAT表中都有一个固定的位置,从不介意将链接多少个DLL。我无法想象如何实现这一目标。

1 个答案:

答案 0 :(得分:12)

可以在没有导入库的情况下链接到DLL,正如MinGW清楚地演示的那样。因此,问题是为什么MSVC决定省略此功能。

原因主要是历史性的。

当时1983年,当Windows出现并设计了DLL时,有许多来自不同供应商的工具链(编译器,链接器)。要求供应商实现对少数操作系统链接“DLL”的支持显然不是一种选择。

所以他们决定编写一个工具来生成一个库,每个人和他们的狗可以链接,即使链接器完全不知道DLL。

除了导入库提供了一些在30年前至关重要的功能,但现在已经过时了。首先是通过序数导入符号的能力 - 即DLL有一个选项,根本不提供任何地址列表;序数是此列表中的索引。当RAM的数量受到严重限制时,就会发现。

其次是对不同名称修改方案的支持。即使在C语言中也有一个名称修改方案,例如FooBar可能会变成_FooBar @ 4(它取决于平台和调用约定)。对于DLL来说,在每个支持的平台上导出“FooBar”以保持一致性是完全合理的(并且它使得GetProcAddress()用户的生命更容易)。导入库实现从_FooBar @ 4到FooBar的映射。

这是基于Raimond Chen的博客(12),他是从一开始就参与Windows开发的人。