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

Seb*_*020 9 c c++ windows dll linker

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

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

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

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

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

Nic*_*sky 12

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

原因主要是历史性的.

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

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

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

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

这是基于博客(1,2雷蒙陈,谁参与的Windows开发从一开始的男子).

  • 我在哪里可以找到有关导入库中确切包含的内容以及它在链接时间、加载时间和运行时间中的工作方式的更多详细信息? (2认同)