【发布时间】:2011-07-16 22:27:09
【问题描述】:
我知道你可以:
-
将 .DLL 文件转换为 .DEF 文件,其中包括其导出
(编辑:这不适用于许多约定) - 将 .DEF 文件转换为 .LIB 文件,您可以使用该文件链接到 DLL
为什么(大多数)链接器不能链接到一个 DLL,只有一个 .DEF 文件,而不是一个 .LIB 文件?
【问题讨论】:
标签: windows linker dynamic-linking function
我知道你可以:
为什么(大多数)链接器不能链接到一个 DLL,只有一个 .DEF 文件,而不是一个 .LIB 文件?
【问题讨论】:
标签: windows linker dynamic-linking function
最终,这里的答案是“因为没有人非常想要它,而且它并没有真正帮助任何事情”。
DEF 文件是为 DLL 创建导入库的输入文件。然后,稍后,当 DLL 被另一个链接使用时,importlib 本身就是一个输入。 importlib 在外面看起来很特别,但当你看里面时,它实际上只是一个稍微特殊的库,里面有对象。
完全可以修改链接器以直接获取 def 文件(或 DLL,就此而言)。
但是链接器的设计中心是它将对象作为输入并输出一个PE可执行文件。因此,将 DEF 或 DLL 作为输入超出了设计模式。
除此之外,它毫无意义——允许链接器将 DEF 文件或 DLL 作为输入既不会启用任何重要的新场景,也不会阻止任何重要的新场景。将您拥有的 DEF 文件(即使没有实际的 DLL)转换为可用的 importlib 只需几分钟的工作(只需为每个 DEF 条目创建假的空函数并链接它)。因此没有理由添加直接链接 DEF 文件的功能。
马丁
就 MSVC 而言,.lib 文件始终是静态库。它们与所有已编译的 .c/.cpp 文件一起作为编译单元链接,因此所有库的代码都包含在您的最终可执行文件中。
然而,一些 .lib 文件(尤其是大多数 Windows 系统文件)仅包含存根,它告诉操作系统在加载时加载所需的 DLL,然后存根将函数调用路由到 DLL。但是,这些存根 静态链接到您的可执行文件中。然后,您的程序将使用 DLL(并获得其所有优点和缺点),但是由于它所需的命名 DLL 函数很高兴位于 .lib 中(因此实际上位于可执行文件本身中),因此您的代码不必知道它正在使用 DLL(特别是使用 declspec(dllimport))。
.def 文件仅在创建 .dll 期间用作一种“设置”或“配置”文件,以指定文件应导出的功能。它不能被链接到,因为它并没有真正描述链接器理解的任何内容。
【讨论】:
您不会将 dll 转换为 DEF 文件。 DEF 只是指示哪些 dll 函数可以从外部访问、导出。
来自docs:
DLL 文件的布局与 .exe 文件非常相似,只有一个 重要区别 — DLL 文件包含导出表。这 导出表包含 DLL 导出的每个函数的名称 到其他可执行文件。这些功能是进入 动态链接库;只有导出表中的函数可以被其他人访问 可执行文件。 DLL 中的任何其他函数都是 DLL 私有的。 可以使用 DUMPBIN 工具查看 DLL 的导出表 使用 /EXPORTS 选项。
您可以使用两种方法从 DLL 导出函数:
创建模块定义 (.def) 文件并在以下情况下使用 .def 文件 构建 DLL。如果要导出函数,请使用此方法 从您的 DLL 中按序号而不是按名称。
在函数定义中使用关键字 __declspec(dllexport)。
使用任一方法导出函数时,请确保使用 __stdcall 调用约定。
使用提供的链接了解有关从 dll 导出的更多信息。
我认为你被否决是因为你的观点不是很清楚,至少对我来说不是。另请检查this。它解释了如何选择导出方法。
【讨论】:
You do not convert a dll to a DEF file 的假设并不总是正确的。我有时会这样做(我见过其他人也这样做),有时是因为 LIB 文件不适用于 DLL。您可能会争辩说您一开始就不应该使用 DLL,但有时会发生这种情况。
Mehrdad,这并不总是关于如何链接到 DLL 的问题,因为我个人从未使用 .DEF 文件链接过 DLL。我 HAVE 所做的是获取别人的 DLL,并且非常辛苦地构建了一个头文件,或者更确切地说,我可以使用的函数原型
LoadLibrary() 在 C 中,Declare Function ... Lib "Foo.dll" Alias "OrdinalName" 在 VB 中,以及
C# 中的[DllImport()]。
当然,很少这样做,就好像您正在使用 DLL 做某事一样,通常您有权这样做,并且作者提供了 .lib 以及与二进制 DLL 文件一起使用的头文件。
我从来没有做过你所说的确切技术,通过将.DEF信息转换为.LIB等...但是,我想获取一个lib或DLL本身并导出.DEF会很容易从中。现在,我实际上已经完成了,在一个项目中,DLL 代码是使用 vbScript 构建的,该 vbScript 从主项目中获取代码,并从所有现有、编译和测试的代码中创建了一个 API .这种复杂程度只是因为我不知道 DLL 中将包含哪些函数,因为主项目可能随时更改,因此静态 .DEF 文件将永远无法工作。所以,我不得不构建一次 DLL,捕获dimpbin /exports,取消修饰函数,然后构建 .DEF 文件,并重新链接 DLL。
如果您发现自己处于这种情况,也许您需要重新考虑您的原始设计,并从那里解决问题...
至于 .LIB 文件,通常您只需要那些用于静态链接的文件,但当 .H 文件可用时也会使用它们,通常使调试变得更好一点。 .
【讨论】: