交叉编译器C中的二进制兼容性

我需要validation一些我怀疑的东西。 如果共享库(.dll)是用C语言编写的,那么使用C99标准并在编译器下编译。 说MinGw。 然后根据我的经验,它是二进制兼容的,因此可以从任何其他编译器使用。 说MS Visual Studio。 我根据自己的经验说,因为我不止一次成功地尝试过它。 但我需要validation这是否是一个规则。

另外我想问一下它是否确实如此,那么为什么用C语言完全用C语言编写的库,例如openCV不为每个不同的操作系统提供编译的二进制文件? 我知道明显的原因是设置所有编译时参数,但除此之外没有正确的吗?

编辑:我正在添加一个额外的问题,我认为这是原始的逻辑扩展。 这不是一个人如何去创建一个封闭的源库吗? 由于提供源的选项不在窗口中,因此给出二进制文件是唯一的选择。 在这种情况下,为尽可能多的体系结构提供二进制文件是理想的结果,C是在系统和编译器之间具有最佳可移植性的明显选择。 对?

在Windows世界中C编译器(MSVC和GCC / MinGW)的特定情况下,假设二进制兼容性是正确的。 可以将GCC编译的C接口DLL链接到Visual Studio中的程序。 这就是像ffmpeg这样的C99项目允许开发人员用Visual Studio编写应用程序的方式。 只需要使用DLL中的Microsoft工具链中的lib.exe创建导入库。 反之亦然,使用mingw.org的pexport或更好的mingw-w64的gendef工具,可以为MSVC生成的DLL创建GCC导入库。

当您进入C ++界面世界时,这种便利的互操作性会崩溃,其中MSVC和GCC的ABI不同且不兼容。 它可能有用,可能没有,没有做出任何保证,并且(目前)没有努力改变它。 此外,调试信息明显不同,直到有人在GCC中编写调试信息生成器/写入器,与MSVC的调试器兼容(当然还有gdb支持)。

我不认为C99特别改变了函数声明的任何内容或者在符号定义中处理参数的方式,因此这里也应该没有问题。

请注意,正如Vijay所说,仍然存在架构差异,因此在链接到AMD64库时无法使用x86库。


还要回答关于闭源二进制文件的附加问题,并为所有可用的编译器/体系结构分发版本。

这正是您创建闭源二进制文件的方式。 除了导入库之外,隐藏DLL的导出也非常重要,使得DLL本身无法用于链接(如果您不希望客户端代码在库中使用私有函数,请参阅例如dumpbin /exports的输出dumpbin /exports MSOffice DLL,那里有很多隐藏的东西)。 你可以用GCC(我相信,从未使用或尝试过)使用像__attribute(hidden)类的东西来实现同样的东西……

一些编译器特定点:

  1. MSVC通过/ MT,/ MD和/ LD提供四个(很好,实际上只有三个在较新版本中)不同的运行时库。 除此之外,您还必须为每个版本的Visual Studio(包括Service Pack)提供构建,以确保兼容性。 但这是封闭源二进制和Windows为您…

  2. 海湾合作委员会没有这个问题; MinGW始终链接到Windows提供的msvcrt.dll(自Windows 98起),等同于/ MD(也可能是与/ MDd等效的调试库)。 但我有两个版本的MinGW(mingw.org和mingw-w64),它们不保证二进制兼容性。 后者更完整,因为它提供64位选项以及32位,并提供更完整的头/库集(包括DirectX和DDK的重要部分)。

一般规则是,如果您的OS / CPU组合具有标准ABI,并且如果ABI对您的语言足够强大,则大多数编译器将遵循该ABI并因此将是二进制兼容的,允许您链接库(共享或用不同的编译器编译到用其他编译器编译的程序就好了。

问题是大多数ABI都相当薄弱 – 它们是围绕C和FORTRAN等低级语言设计的,可以追溯到像C ++这样的面向对象语言之前的日子。 因此,他们往往缺乏对函数重载,用户定义的运算符,exception,全局构造函数和析构函数,虚函数,inheritance等C ++所需的支持。

在设计C ++时,这种缺乏得到了认可,这就是为什么C ++具有extern "C" – 这导致编译器将自己限制为某些function的标准ABI,同时禁用ABI通常不支持的所有额外C ++function。

编译到特定体系结构的共享库或DLL可以链接到由针对相同体系结构的其他编译器编译的应用程序。 (根据架构,我的意思是处理器/ OS组合)。 但是,对于库开发人员来说,编译所有可能的体系结构是不切实际的。 此外,当库以源代码forms分发时,用户可以构建针对其特定需求优化的二进制文件。