20

我来自 Linux 世界,知道很多关于维护用 C++ 语言编写的动态库 API 的向后二进制兼容性 (BC) 的文章。其中之一是“C++ 的策略/二进制兼容性问题” ,它基于GCC 编译器使用的Itanium C++ ABI 。但是对于 Microsoft C++ 编译器(来自 MSVC),我找不到任何类似的东西。

我了解大多数技术适用于 MS C++ 编译器,并且我想发现与 ABI 差异(v-table 布局、修改等)相关的编译器特定问题

所以,我的问题如下:

  • 在维护 BC 时,你知道 MS C++ 和 GCC 编译器有什么区别吗?
  • 我在哪里可以找到有关 MS C++ ABI 或有关在 Windows 中维护 API BC 的信息?

任何相关信息将不胜感激。
非常感谢你的帮助!

4

3 回答 3

24

首先,这些政策是通用的,不仅仅指 gcc。例如:函数中的私有/公共标记是特定于 MSVC 而不是 gcc 的。

所以基本上这些规则也完全适用于 MSVC 和通用编译器。

但...

你应该记住:

  1. GCC/C++ 自 3.4 版本以来一直保持其 ABI 稳定,大约 7 年(自 2004 年以来),而 MSVC 在每个主要版本中都会打破其 ABI:MSVC8(2005)、MSVC9(2008)、MSVC10(2010)彼此不兼容。
  2. 与 MSVC 一起使用的一些常用标志也会破坏 ABI(如异常模型)
  3. MSVC 对于调试和发布模式有不兼容的运行时。

所以是的,您可以使用这些规则,但与 MSVC 的通常情况一样,它有更多的怪癖。

另请参阅“关于二进制兼容性的一些想法”,Qt 也使它们的 ABI 与 MSVC 保持稳定。

注意我有一些经验,因为我在CppCMS中遵循这些规则

于 2011-01-24T14:05:12.157 回答
9

在 Windows 上,您基本上有 2 个选项来实现长期二进制兼容性:

  1. 通讯
  2. 模仿 COM

在这里查看我的帖子。在那里,您将看到一种跨不同编译器和编译器版本以二进制兼容的方式创建 DLL 和访问 DLL 的方法。

C++ DLL 插件接口

于 2011-01-28T11:02:09.730 回答
8

MSVC 二进制兼容性的最佳规则是使用 C 接口。根据我的经验,唯一可以摆脱的 C++ 特性是单继承接口。因此,将所有内容都表示为使用 C 数据类型的接口。

这是兼容二进制的东西的列表:

  • STL。二进制格式甚至只是在调试/发布之间发生变化,并且取决于编译器标志,因此最好不要使用 STL 跨模块。
  • 堆。不要new/malloc在一个模块中和delete/free在另一个模块中。有不同的堆彼此不知道。STL 不能跨模块工作的另一个原因。
  • 例外。不要让异常从一个模块传播到另一个模块。
  • 来自其他模块的 RTTI/dynamic_casting 数据类型。
  • 不要相信任何其他 C++ 特性。

简而言之,C++ 没有一致的 ABI,但 C 有,所以要避免 C++ 特性跨模块。因为单继承是一个简单的 v 表,所以您可以有用地使用它来公开 C++ 对象,前提是它们使用 C 数据类型并且不进行跨堆分配。这也是 Microsoft 自己使用的方法,例如用于 Direct3D API。GCC 可能有助于提供稳定的 ABI,但标准并不要求这样做,而 MSVC 充分利用了这种灵活性。

于 2011-01-28T21:56:36.230 回答