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

时间:2011-07-25 13:49:46

标签: c shared-libraries binary-compatibility

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

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

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

3 个答案:

答案 0 :(得分:6)

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

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

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

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


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

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

一些编译器特定点:

  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的重要部分)。

答案 1 :(得分:4)

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

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

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

答案 2 :(得分:2)

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

相关问题