C++ 导入库是如何工作的,为什么';你不需要它们吗?

C++ 导入库是如何工作的,为什么';你不需要它们吗?,c++,c,windows,dll,linker,C++,C,Windows,Dll,Linker,我看了这一页: 它解释了链接器需要导入库,因为编译器无法区分普通函数调用和API函数调用。但是他们也说uu declspec(dllimport)将函数调用指定为API调用,因此链接器链接到\uu imp.[function name]但是使用此关键字,编译器应该知道这是对API函数的调用 为什么链接器仍然需要导入库?编译器可以通过在函数名前面加上\uuuu imp\uuu将此符号标记为导入,并可以调用函数指针(这是一个尚未解析的符号),链接器可以用IAT条目的地址替换此符号(因为它认为这是一个

我看了这一页:

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

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

为什么MinGW链接器可以直接使用“MinGW DLL”,而VisualStudio链接器需要一个导入库


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

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

原因主要是历史性的

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

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

此外,导入库提供了一些30年前非常重要但现在几乎过时的功能。首先是能够按顺序导入符号,即DLL可以选择不提供任何名称,只提供地址列表;序号是此列表中的索引。当RAM的数量受到严重限制时,这一点非常重要

第二是支持不同的名称篡改方案。即使在C语言中也有一个名称混乱的方案,例如FooBar可能会变成_FooBar@4(这取决于平台和调用约定)。DLL在每个受支持的平台上导出“FooBar”以实现一致性是非常有意义的(而且它使GetProcAddress()用户的生活更加轻松)。导入库从实现映射_FooBar@4到FooBar


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

回答了您的大部分问题。我在哪里可以找到导入库中具体包含的内容以及它在链接时间、加载时间和运行时间中的工作方式的详细信息?Chen:“该.dll不包含链接器需要的所有信息”…“如果我有一个程序(myprogram.c)调用某个动态库a.dll中定义的c函数
void someFunction(int)
,编译myprogram.c->myprogram.obj时,编译器是否会在myprogram.obj中生成与.dll中的符号匹配的占位符
someFunction
,就像.dll是静态库(a.lib)时一样?为什么DLL不能像.lib或.obj文件那样直接链接?PE格式不支持这个吗?另外,似乎dll文件中有导出符号,如果我执行
dumpbin/exports someDll.dll
操作,我会得到很多条目,而且函数的符号(名称)似乎与导入库文件中的符号(名称)匹配;如果dll有这些信息,为什么我还需要一个库?VS只是没有被编程来加载DLL并解析这些信息吗?