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

How do import libraries work and why doesn't MinGW need them?

本文关键字:MinGW 为什么 不需要 何工作 工作 导入      更新时间:2023-10-16

我看了这个页面:深入了解Win32可移植可执行文件格式

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

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

为什么 MinGW-linker 可以直接使用"MinGW-DLL",而 Visual-Studio 链接器需要一个导入库?

当我阅读这篇文章时,还提出了其他一些问题。在与最终可执行文件的链接完成之前,"dlltool(或链接器)"(以创建导入库为准)如何知道 IAT 条目的位置?我认为 IAT 条目将在链接时与最终可执行文件一起构建。该帖子说,每个API调用在IAT表中都有一个固定的位置,更不用说将链接多少DLL。我无法想象如何能够做到这一点。

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

原因

主要是历史原因。

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

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

此外,导入库提供了一些 30 年前至关重要但现在几乎过时的功能。首先是按序数导入符号的能力——即.DLL可以选择根本不提供名称,只提供地址列表;序号是此列表中的索引。当 RAM 的数量受到严重限制时,变得有意义。

二是支持不同的名称重整方案。即使在 C 语言中也存在名称重整方案,例如 FooBar 可能会变得_FooBar@4(这取决于平台和调用约定)。DLL在每个受支持的平台上导出"FooBar"以实现一致性是完全有意义的(它使GetProcAddress()用户的生活更容易)。导入库实现了从_FooBar@4到FooBar的映射。

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