我正在寻找有关dlltool的--add-indirect选项的更多信息。你什么时候使用这个选项?它做了什么?
-a
--add-indirect
指定
dlltool
创建导出文件时应添加 允许导出函数不带引用的部分 使用导入库。不管这到底意味着什么!
答案 0 :(得分:2)
首先,让我们清楚说明什么是导出文件。创建DLL需要导出文件。该文件与构成DLL体(即函数,类等)的目标文件(由编译器生成)链接,并处理DLL与外部世界之间的接口。这是一个二进制文件,可以通过在-e
创建或读取dlltool
文件时向*.def
提供dlltool
选项来创建。
您必须了解的下一个术语是导入库。某些使用者应用程序使用DLL的方法之一是将此应用程序与DLL链接,以便DLL中的所有导出功能都可供消费者使用。这种到DLL的链接通常是通过链接到导入库来完成的,导入库本质上是一个辅助静态库,它包含一个导入地址表(IAT),允许消费者引用所有DLL导出的功能。例如,每个引用的DLL函数在IAT中包含其自己的条目。在运行时,IAT填充了适当的地址,这些地址直接指向单独加载的DLL中的相应函数。
现在让我们手动创建一个包含gcc
和gcc -c library.c
的DLL,让您感受到正在发生的事情:
library.o
生成dlltool -e exports.o -l library.dll.a library.o
,
exports.o
生成导出文件library.dll.a
和导入库.dll.a
(.a
是GCC生成的导入库的常规后缀,强调导入库实际上是静态的{{1 },但是针对带有.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
回到正轨,既然我们知道基本的术语和目的,我们就可以轻松地解释有关--add-indirect
的帮助中的内容:
指定
dlltool
创建导出文件时应添加 允许导出函数不带引用的部分 使用导入库。不管这到底意味着什么!
让我们将其应用于上一个示例。在这种情况下,exports.o
已经包含IAT,因此生成的library.dll
也会包含该信息,因此我们不需要导入库library.dll.a
,因为现在我们可以直接链接到{{ 1}}本身:
library.dll
是否有用是一个非常主观的问题。我想从我们(程序员/用户)的角度来看,它几乎没用,因为无论如何都不应该明确地(即通过直接调用gcc consumer.o library.dll -o consumer
)进行DLL创建和链接,而应该通过GCC完成前端(如上所述)。从构建工具链(如GCC本身)等开发工具的角度来看,这可能很有用,因为类似于上面例子的东西实际上可以在GCC本身后面用于执行dlltool
等等。
最后,通常不鼓励直接链接DLL。虽然它适用于最新版本的MinGW / MinGW-w64,但它在过去已经有过bug。此外,如果禁用伪重定位,则与DLL直接链接可能会导致某些运行时问题。此外,这是MSVC将消费者与DLL链接的官方方式,即没有导入库,MSVC根本无法进行链接,也可能是您更喜欢始终使用导入库的原因。记住DLL与Linux上的共享对象(SO)不同:它们的用例是相同的,但它们的实现基于不同的技术。