2015-07-10 85 views
2

尽量不要对这个问题很难判断我。不同编译器的DLL兼容性

如果我尝试在用MinGW工具链(g ++)编译的Visual Studio项目中使用DLL(用C++编写),会出现问题吗?

如果答案是肯定的,有人可以解释我为什么吗?

回答

4

只要执行代码,如果它的目标是Windows,那么它应该运行。

对于互操作性;它取决于从dll公开的API。

  • 如果是“C”风格的API,那么你应该没问题。
  • 如果它是具有类和STL使用的C++ API,那么使用不同的编译器(甚至编译器中的不同设置)可能会遇到麻烦。 C++没有标准的ABI。

作为评价和价值可能触及这里要注意; “C”风格的API不仅仅是函数调用,兼容性包括(但不限于)诸如;

  • 内存分配;一般的规则是“解除分配必须由相同的代码分配来进行” - 即,在DLL等时所使用的匹配分配/解除分配(例如newdeletemallocfreeCustomAllocCustomDealloc
  • 数据对齐和包装,不是所有的编译器具有相同的默认
  • 调用约定,同样,并非所有编译器具有相同的默认值,如果有疑问,可以在该公约应该是什么(如__stdcall

至于明确C++ ABI除上述所有之外,不兼容性包括Ë;

  • 名称重整
  • STL类和容器实现的newdelete
  • 独立和不同的实施方式中,使用自定义存储器池等等
  • 异常的机制,例如生成和栈展开

这些都是不全面的名单,但他们在一定程度上激励一般建议,如果可能的话,使用相同的工具链和相同的编译器/连接设置

+0

例如,'的std :: string'和'性病:: Set '或'std :: cout'可能在MinGW和Visual Studio之间有不同且不兼容的实现。名称可能会有所不同。还有异常处理。 –

+0

TBH有一个**接口**提到'std :: cout'会很奇怪。在DLL中使用'std :: cout' **完全可以。但是,不要指望MinGW端的'std :: cout << std :: hex'影响VC++端的'std :: cout'对象。 OTOH,如果你返回由'new'分配的'int *',它可能看起来是类型的C接口,但调用delete ptr的要求仍然使它成为一个C++接口。 – MSalters

-3

不,因为它都是一个标准。事实上,你使用gcc编译的C++应用程序会从操作系统的dll文件中调用系统函数。所以无论你是手动还是自动调用它们,都是一样的。

+1

错误。 ABI可能不同。标准C++库内部结构(例如'std :: map'或'std :: string'的实现细节和结构布局)是不同的。该标准定义了C++源代码中实现的行为。它不知道编译器。 –

+1

对于所有downvoters和以前的评论。编译代码没有区别,因为它是机器代码+系统调用,结构有点不同 - 这就是事实,但不是简单的函数。但只要你用C风格编码就没有区别。您的程序需要Windows库才能启动,并会调用这些dll。所以总结起来 - 你必须做出一些thigns小心 – Chlorek

+1

但你不能切实地连接起来了'.obj'对象使用MinGW编译成库(包括C++标准之一)与VisualStudio中,反之亦然编译的文件。你甚至会在基于GCC 4.9的MinGW和基于GCC 5的MinGW之间出现兼容性问题!实际上,一个C++头文件包含很多内部'struct'-s或'class'es和'inline'-d函数(或方法),这些都是不同的......而异常处理也是不同的...... .. –

0

问题不在于DLL。这是关于如何将这种DLL描述到您的编译器(即头文件和导出)。

这些描述会影响您的代码在数据布局上的预期效果(例如,不同的编译器可能有不同的默认对齐和填充),甚至不同的代码路径(例如,解析为不同的内联函数和宏,比如在STL情况下)。

然后每个编译器可能有不同的名字改编方案,您可能需要一点黑客粘上代码。

用很特殊的照顾就上述问题,你应该使用不同的编译器一个DLL被罚款。