10

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

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

编辑:我添加了一个附加问题,我认为这是对原始问题的逻辑扩展。这不就是创建一个封闭源代码库的方式吗?由于提供源的选项在那里消失了,因此提供二进制文件是唯一的选择。在这种情况下,为尽可能多的架构提供二进制文件是理想的结果,而 C 显然是在系统和编译器之间具有最佳可移植性的选择。对?

4

3 回答 3

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 本身无法用于链接(如果您不希望客户端代码使用库中的私有函数,请参见例如dumpbin /exportson的输出) MSOffice DLL,那里有很多隐藏的东西)。您可以使用诸如此类的东西使用 GCC(我相信,从未使用或尝试过)来实现相同的目标__attribute(hidden)......

一些编译器特定点:

  1. MSVC 通过 /MT、/MD 和 /LD 提供了四个(好吧,实际上在较新版本中只剩下三个)不同的运行时库。最重要的是,您必须为每个版本的 Visual Studio(包括 Service Pack)提供构建以确保兼容性。但那是封闭源代码二进制文件和 Windows 对你来说......

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

于 2011-07-25T14:21:32.257 回答
4

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

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

This lack was recognized when C++ was designed which is why C++ has extern "C" -- which causes the compiler to limit itself to the standard ABI for certain functions, while disabling all the extra C++ features that the ABIs generally don't support.

于 2011-07-25T17:10:04.913 回答
2

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

于 2011-07-25T14:06:17.347 回答