【问题标题】:How do import libraries work and why doesn't MinGW need them?导入库是如何工作的,为什么 MinGW 不需要它们?
【发布时间】:2015-03-05 14:55:28
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • This post 回答了您的大部分问题。

标签: c++ c windows dll linker


【解决方案1】:

可以在没有导入库的情况下链接到 DLL,MinGW 清楚地表明了这一点。因此问题是为什么 MSVC 决定省略此功能。

原因主要是历史原因。

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

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

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

其次是对不同名称修改方案的支持。即使在 C 中也有一个名称修改方案,例如 FooBar 可能变为 _FooBar@4 (这取决于平台和调用约定)。 DLL 在每个支持的平台上导出“FooBar”以保持一致性是非常有意义的(它使 GetProcAddress() 用户的生活更轻松)。导入库实现_FooBar@4到FooBar的映射。

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

【讨论】:

  • 我在哪里可以找到有关导入库中究竟包含什么以及它在链接时、加载时和运行时如何工作的更多详细信息?
  • Chen: ".dll 不包含链接器需要的所有信息"..." 如果我​​有一个程序 (myprogram.c) 调用某些 C 函数 void someFunction(int)动态库 a.dll,编译 myprogram.c -> myprogram.obj 时编译器不会在 myprogram.obj 中生成一些占位符 someFunction,它会匹配 a.dll 中的符号,就像 a.dll 是静态的一样库(a.lib)代替?为什么不能像.lib或.obj文件一样直接链接dll?PE格式不支持吗?
  • 另外,似乎在 dll 文件中有导出的符号,如果我这样做 dumpbin /exports someDll.dll 我会得到很多条目,而且函数的符号(名称)似乎与导入库文件中的那些;如果 dll 有这些信息,为什么我还需要一个 lib? VS 只是没有编程来加载 DLL 并解析这些信息吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 2014-05-04
  • 2012-05-15
  • 1970-01-01
  • 2018-04-13
  • 1970-01-01
  • 2017-02-24
相关资源
最近更新 更多