【问题标题】:C portable shared library interface: best practice on primitive typesC 可移植共享库接口:基本类型的最佳实践
【发布时间】:2021-12-23 13:02:24
【问题描述】:

问题:

最近我们的 C 共享库遇到了以下问题。
该库定义了一个类似这样的方法:

typedef enum {A, B, C} some_enum;
typedef struct {some_enum e; time_t t; char* data;} request;
void f(request);

我们使用 clang 及其交叉编译功能为多种架构编译了该库。其中一个平台是 Windows 32 位。
这就是问题所在:当尝试在使用 MSVC 32 位编译器的示例中使用该库时,该示例因 seg 错误而失败。
原因:在 MSVC 32 位 time_t 中为 8 个字节,而在 Windows 32 位的 clang 编译中假定为 4 个字节。

显然,如果我们使用固定宽度的整数类型,例如int64_t,则永远不会出现此问题。

问题:

对于可移植的 C 共享库中的原始类型,是否有既定的最佳实践?

例如,在 C 共享库接口中完全避免任何非固定宽度整数类型是最佳实践吗?
例如,enums 在可移植 C 库中是否“允许”(就最佳实践而言)?

【问题讨论】:

  • 请注意,这与编译器无关:您使用标准 C 运行时库(具体为time.h)的两个不兼容实现来编译共享库和应用程序代码。
  • @yugr 谢谢,这是一个非常有用的观察,我错过了。我认为它仍然与编译器有关,因为我希望在 Linux Arm 64 架构中完成的编译与该系统上可用的默认 C 运行时库兼容。
  • 并非总是如此,例如Linux 上不同的 libc 实现(Glibc、newlib、musl 等)肯定兼容。至于你的情况,你能用-E编译有问题的代码并检查哪个头文件提供time_t吗? (对于 MSVC,您可以通过在 Visual Studio 编辑器中“打开”time.h 来执行此操作。
  • 注意:Windows 有__time64_t__time32_t_USE_32BIT_TIME_T macro determines 其中一个time_t 是类型定义的。
  • 谢谢@YakovGalka,很高兴知道。

标签: c shared-libraries portability


【解决方案1】:

通常,给定平台的所有编译器都会非常努力地保留默认的 C ABI。违反 ABI 通常被认为是编译器错误。

由于各种原因,C++ ABI 更加棘手,但至少 Clang tries hard 也可以在 Windows 上保留该 ABI。

C ABI 兼容性意味着,除其他外,所有原始类型都已定义大小和对齐方式,因此无需使用固定宽度类型(即long 将与 all 相同特定目标的编译器)。

至于您的情况,我怀疑 clang 和 cl.exe 出于某种原因使用了不同的 time.h,因此我建议对此进行调查(请参阅我上面关于如何进行此操作的评论)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 2015-09-26
    • 1970-01-01
    相关资源
    最近更新 更多