2

我正在寻找有关 dlltool 的 --add-indirect 选项的更多信息。你什么时候使用这个选项?它有什么作用?

来自 binutils 的有关此选项的帮助信息:

-a
--add-indirect

指定当dlltool创建导出文件时,它应该添加一个允许在不使用导入库的情况下引用导出函数的部分。不管这意味着什么!

4

1 回答 1

2

首先,让我们明确什么是导出文件。创建 DLL 需要导出文件。该文件与构成 DLL 主体(即函数、类等)的目标文件(由编译器生成)链接,并处理 DLL 与外部世界之间的接口。这是一个二进制文件,可以通过在创建或读取文件时提供-e选项来创建它。dlltool*.def

您必须了解的下一个术语是import library。一些消费者应用程序使用 DLL 的方法之一是将此应用程序与 DLL 链接起来,以便消费者可以使用从 DLL 导出的所有功能。这种到 DLL 的链接通常是通过链接到一个导入库来完成的,该库本质上是一个辅助静态库,其中包含一个导入地址表(IAT),它允许消费者引用所有 DLL 导出的功能。例如,每个引用的 DLL 函数在 IAT 中都包含自己的条目。在运行时,IAT 会填充适当的地址,这些地址直接指向单独加载的 DLL 中的相应函数。

现在让我们手动创建一个 DLLdlltoolgcc让您感受发生了什么:

gcc -c library.c

产生library.o,

dlltool -e exports.o -l library.dll.a library.o

生成导出文件exports.o和导入库library.dll.a.dll.a是 GCC 生成的导入库的常规后缀,强调导入库实际上是静态的.a,但针对 DLL 的.dll),

gcc library.o exports.o -o library.dll

产生library.dll,

gcc consumer.o library.dll.a -o consumer

consumer.exe生成与 .链接的可执行文件library.dll

注意:以上是创建 DLL 的手动过程,不鼓励在生产中这样做,因为 GCC 将所有这些逻辑包装在一个优化的调用中:

gcc -shared -o library.dll library.o -Wl,--out-implib,library.dll.a

回到正轨,现在我们知道了基本的术语和目的,我们可以很容易地解释 help about 中写的内容--add-indirect

指定当dlltool创建导出文件时,它应该添加一个允许在不使用导入库的情况下引用导出函数的部分。不管这意味着什么!

让我们将其应用于前面的示例。在这种情况下,exports.o将已经包含 IAT,因此结果library.dll也将包含该信息,因此我们不需要导入库library.dll.a,因为现在我们可以直接链接到library.dll自身:

gcc consumer.o library.dll -o consumer

它是否有用是一个非常主观的问题。我想从我们(程序员/用户)的角度来看,它几乎没有用,因为dlltool无论如何都不应该明确地(即通过直接调用)来完成 DLL 的创建和链接,而应该通过 GCC 前端来完成(如前所述以上)。从构建诸如工具链(如 GCC 本身)之类的开发工具的角度来看,这可能很有用,因为与上述示例类似的东西实际上可能由 GCC 本身在幕后使用来执行gcc -shared -o library.dll ...等。

最后,通常不鼓励直接链接 DLL。虽然它在最新版本的 MinGW/MinGW-w64 上运行良好,但过去已知它存在错误。此外,如果禁用伪重定位,则与 DLL 的直接链接可能会导致某些运行时问题。此外,这是 MSVC 将消费者与 DLL 链接起来的官方方式,即没有导入库,MSVC 根本无法进行链接,这也可能是您应该始终使用导入库的原因。请记住,DLL 与 Linux 上的共享对象 (SO) 不同:它们的用例相同,但它们的实现基于不同的技术。

于 2013-12-13T15:33:37.950 回答