具有C 接口的C 动态库如何在不同的编译器版本之间不会破坏ABI

How can a C++ dynamic library with a C++ interface not break ABI between different compiler versions?

本文关键字:之间 版本 ABI 编译器 动态 接口 具有      更新时间:2023-10-16

最近,我一直在为我的爱好3D图形引擎项目使用Assimp库来加载3D型号。

库以DLL的形式出现,并附有导入库(LIB)和EXP文件(仅在最新来源构建时;我知道它具有有关导出功能的信息,类似于LIB)

现在,让我提出这个问题的惊喜部分是:

我能够正确地使用任何构建/链接错误或运行时错误使用库的两个不同版本的C 接口:

  • 预先构建的库,版本3.1.1,该库是构建并取决于较旧的运行时(MSVCP110.DLLMSVCR110.DLL)(我后来决定更改为自己的构建,因为该二进制构建中存在链接错误)
  • 我自己由VS 2013编译器制成的源构建,具体取决于MSVCP120.DLLVCRUNTIME120.DLL

我能够将这两个库二进制文件与我的可执行二进制文件一起使用:

  • vs 2013编译器
  • vs 2015编译器

我惊讶地使用图书馆的成功,如上所述,没有任何错误,是由:

引起的。
  • 在Internet上阅读有关C 库和接口如何在不同编译器版本之间不兼容(ABI),因此无法与其他编译器构建的二进制文件一起使用。例外:通过C界面的用法,可以保持ABI兼容性;com库(构建COM接口是为了克服同一问题)。
  • 使用使用不同编译器构建的二进制文件可能会因为功能名称操作而引起问题(可能由导入库解决吗?!),动态内存分配和由分配器/destructors的不同版本完成的动态内存分配和释放。

任何人都可以就我成功地使用VS 2013构建的动态库以及VS 2015 Toolset应用程序而没有任何上述问题的VS 2013构建的动态库,也可以提供一些有关此用例的见解?另外,当使用VS 2013构建和VS 2015构建我的3D引擎应用程序时,使用预构建的二进制文件时也适用。这是孤立的情况,还是Assimp库本身负责这些问题,并以这种方式实施以确保兼容性?

库的实际用法非常简单:我使用了进口商对象(类)的局部堆栈变量,并从那里从那里进行了操纵并从一堆结构中读取信息;没有其他类(我认为)

只要DLL中使用的所有类和内存都在类内分配,释放和维护,并且您不使用界面边界上的标准库容器对象,您就完全是安全地做。

如果模块使用不同的编译器,甚至使用不同的CRT使用情况,或者至少使用了不同的CRT,则甚至不允许在DLL边界上使用Std:String。

实际上,使用普通接口(纯虚拟类)对于所有VS C 编译器都是安全的。也使用外部" C"很安全。

因此,如果您交换的结构只是豆荚或具有简单的普通数据对象,并且只要在DLL内部进行分配和破坏,则可以自由混合并使用不同的编译器构建DLL。

最好的例子是Windows OS的DLL。他们使用了简单数据结构的明确定义的接口。内存管理和分配(例如Windows,Menus,GDI对象)是通过透明的手柄完成的。DLL只是您的黑框。

希望我能遇到所有积分。