VisualStudio和gcc之间的*.dll *.a *.lib *.def文件的兼容性问题

24

这非常令人困惑。我花了很多时间在Stack等网站上阅读文章,但仍然感到困惑。

我正在使用Qt和C++进行编码。在Qt中,我使用gcc选项作为编译器。
问题是,我尝试过许多第三方库,但它们似乎都不能正常工作。

我对.dll、.a、.lib、.def文件和库架构很陌生。

问题1:

根据我的有限经验(到目前为止我已经尝试了7或9个库),库的供应商很少告诉你.dll是由VisualStudio还是gcc制作的。这增加了很多困惑。他们几乎从不明确说明库与哪个编译器兼容。所以我会欣赏一些关于如何处理这个噩梦的实际建议。我尝试过的几乎所有库都是开源项目。我不会在这里点名,但这些都是知名项目。我相信问题出在我缺乏知识上...

MinGW和gcc世界

问题2:
据我所知,MinGW gcc宇宙中的动态C++库需要这些东西,是吗?
*.h
*.dll
*.a

问题3:
不幸的是,.a文件经常丢失,库就不能正常工作。这非常令人困惑。如果缺少.a文件,我该怎么办?

问题4:
如果*.dll是由gcc制作的,我可以为MinGW/gcc生成.a文件吗?

问题5:
如果*.dll是由VisualStudio制作的,我可以为MinGW/gcc生成.a文件吗?

问题6:
可能一些*.dll(使用MinGW/gcc制作)过于陈旧而不再与较新的MinGW/gcc兼容,是吗?

问题7:
使用MinGW/gcc的Qt项目不需要*.lib文件,对吗?那只有在使用VisualStudio时才需要,对吗?

问题8:
在使用MinGW/gcc的Qt项目中,我不需要一个*.def文件来使用一个*.dll,对吗?

VisualStudio World

问题9:
据我所知,VisualStudio的动态C++库需要以下文件:
*.h
*.dll
*.lib

对吗?问题在于 *.lib 文件几乎总是缺失的。此外,没有明确指示该库与哪个编译器兼容。那么我怎么知道它只适用于VisualStudio还是其他编译器也可以使用呢?

问题10:
如果缺少.lib文件,我就没戏了吗?

问题11:
如果*.dll是由VisualStudio制作的,我能否为VisualStudio生成.lib文件?如何实现?

问题12:
如果*.dll是由MinGW/gcc制作的,我能否为VisualStudio生成.lib文件?如何实现?

问题13:
可能存在这样一种情况:*.dll(由VisualStudio制作)太旧了,不再与新版本的VisualStudio兼容吗?

问题14:
如果我在Qt Creator中选择VisualStudio编译器,这是否与其他人使用真正的VisualStudio编译器编译的动态库100%兼容?我相信Qt Creator中的VisualStudio编译器选项是虚假的。

问题15:
如果我在QtCreator中选择MinGW/gcc编译器,是否可以将其与其他人使用真正的VisualStudio编译器编译的Qt动态库一起使用?

问题16:
我在Qt项目中使用MinGW/gcc时不需要*.def文件来使用*.dll,对吧?

问题17:
我能否将使用真正的VisualStudio制作的*lib(适用于*.dll和*.h)文件转换为*.a文件,以便我可以在Qt gcc项目中使用未修改的*.dll和*.h文件?


3
我相信这种复杂性是 Windows 特有的,如果在 Linux 上使用 Qt,你就不会遇到这种情况! - Basile Starynkevitch
2
你可能希望将此问题分解为多个问题(特别是“如果我有 Y,我可以生成 X 吗”这种问题)...很多人可能可以回答其中一些问题,如果您单独询问它们(因为它们与 Qt 没有太大关系),关于 windows 链接的问题,你可能会得到更快的回复。话虽如此,我可以给你最简短的答案是:* 如果不必使用 MinGW,则不要使用它 * - VisualStudio 是该平台支持的标准,长期来看您会有更好的体验(如果在短期内使用开源库依赖项时会有些麻烦)。 - Nick Bastin
3
-1:因一次性提出16个问题而受到批评。 - Nicol Bolas
1
@Nicol:我没有一次性提出16个问题。我把一个问题分成小而独立的部分,这样细节不会丢失。我的问题是关于dll兼容性的。兼容性是一个宏观概念。 - user1118167
@Basile - 但是如果你试图在Linux上运行Visual Studio(使用wine?),你将面临更糟糕的复杂性。使用操作系统的本地编译器总是更容易的。 :-) - Bo Persson
我认为,在阅读了Levine的书《Linkers & Loaders》之后,Unix对于*.so动态链接的设计比Windows中的*.dll+*.lib+*.def更好。 - Basile Starynkevitch
5个回答

18

也许从头开始并不跳过自己,描述核心问题会更有价值。由此可以得出几个问题的答案。

起点是ABI(应用程序二进制接口)。这定义了以下内容:

  • 如何调用函数,例如哪些参数进入哪些寄存器或它们放在堆栈上的位置
  • 如何抛出异常
  • 对象的布局方式,例如“vtable指针”的位置,使用哪种填充
  • 内置数据类型的大小
  • 如何将函数名“mangle”为符号
  • 类型信息的布局方式
  • 标准库类的布局
  • 等等

大多数平台定义了C ABI但没有定义C++ ABI。因此,编译器为除C之外的所有内容定义自己的ABI(通常其中包括C内容)。这会产生在不同编译器之间(甚至是同一编译器的不同版本之间)不兼容的目标文件。

通常,这表现为看起来奇怪的名称未定义:不同的ABI有意使用不同的名称重整以防止意外地链接无法工作的可执行文件。要解决这些问题,您最好使用相同的编译器构建所有组件。

如果您想确定库是使用哪个编译器构建的,可以使用适当的工具查看其内容。我知道的只有UNIX工具(它们可能在MingW中可用):

  • nm以查看符号名称(通常与less或grep一起使用)
  • ar以构建或检查库
  • ident查找嵌入在对象中的特殊字符串
  • strings查找所有字符串
  • c ++filt将符号解除混淆为其C ++声明

查看符号通常会导致识别出产生它们的编译器。如果您已经看到了足够多次,甚至可以从符号本身判断ABI。

这个领域里还有很多内容,但是我已经力不从心了... :-) 无论如何,我认为这回答了上面几个问题。


9
我在搜索用于使用Code::Blocks c++编译器创建.a文件的工具时,偶然发现了这个问题。Code:Blocks使用MinGW gcc编译器。我认为它在谷歌上排名很高,证实了我的巫术。
动态链接库(dll)是一个混合的群体。有些可以编译成使它们在编程语言和编译器之外很难使用的方式。
然而,通常情况下,dll是使用干净的C接口创建的。如果是这种情况,我认为我可以回答你的问题:
1:那不是一个问题。
2、9:是的
3、10:不是
4、11:是的。MinGW包括一个工具(dlltool.exe),可以将.dll和.def文件创建为.a文件。MS VisualStudio也包括一个工具(我认为叫做lib.exe)来完成同样的事情。如果您开始使用另一个编译器,您可能会发现他们也有一个工具。Borland编译器有implib.exe工具。
5、12:是的(与4相同)
6、13:哎呀...我不认为dll有过期日期,但它们必须为正确的操作系统编译。
8、16:您需要.def才能制作.a或.lib,如果没有,实际上可以从.dll创建.def。

5
DLL本质上是一个已编译的应用程序,只不过它是以函数库的形式而非EXE文件存在。其他任何应用程序都可以通过声明函数、包含该函数的DLL以及参数和返回值等来使用该DLL中的函数。
如果使用“动态链接库”编译应用程序,则必须在系统上已有相应的DLL,因此您必须将必要的DLL包含在安装程序中,或者希望它们已经存在于目标计算机上。使用DLL可以使您的应用程序整体大小更小。
创建DLL与创建任何其他应用程序一样-只需将构建目标指向DLL而非EXE或其他内容即可。
要创建任何应用程序-DLL、EXE或其他-您需要必要的源代码和头文件。 .h文件包含函数、数据类型和类等的声明,但它们很少包含代码。 .def与.h非常相似,但通常是用于链接器的一组指令。
当您编译时,.h或.c或其他文件会变成.obj-对象文件。多个对象文件连接在一起以创建您的DLL或EXE。
.lib文件是静态库-实质上是一堆已合并到链接阶段的.obj文件(或一个.obj)。
.obj和.lib文件的格式可能特定于编译器,并且它们很少在编译器之间兼容。您必须拥有原始源代码或专为您的编译器制作的.obj或.lib。
当您选择使用“动态链接库”制作EXE时,它将期望使用DLL。当您选择“静态链接库”时,链接器将在生成EXE之前找到它所需的.lib文件,并且您不需要那些DLL。

2
问题1:您应该通过链接器命令导入.h文件和链接.a文件,并将.dll复制到您的.exe输出附近。
问题2:您可以通过.def文件创建.a文件。
set PATH=C:\Program Files\CodeBlocks\MinGW\bin;%PATH%

dlltool.exe -d libfftw3-3.def -l libfftw3-3.a

问题3:不,您可以手动制作.def文件,然后制作.a文件。

问题4、5:是的。

问题6:我认为这取决于您的硬件和操作系统,而不是您的编译器。

问题7:我不知道。

问题8:您只需要.h .a .dll,不需要.def文件。

问题9:.lib文件是为Visual Studio准备的。

问题10:不,您需要.def.dll来制作.lib文件,如果没有,可以自己制作.def文件。

set PATH=C:\Program Files\Microsoft Visual Studio 12.0\VC\bin;%PATH%

lib /machine:x86 /def:libfftw3-3.def

或者

lib /machine:x64 /def:libfftw3-3.def

问题11:是的,我在上面告诉过你。
问题12:是的。
问题13:不。

0
我知道这是一个老问题,但最近我遇到了类似的问题。
除了Lars Betak上面的答案,请注意,如果两边的代码没有使用相同的标准库,调用纯C DLL可能会产生非常奇怪的结果。GCC和MSVC的标准库肯定是不同的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接