C 可移植共享库接口:原始类型的最佳实践

C portable shared library interface: best practice on primitive types

问题:

最近我们的 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 位编译器的示例中使用该库时,该示例因段错误而失败。
原因:在 MSVC 32 位 time_t 中是 8 个字节,而在 Windows 32 位的 clang 编译中它被假定为 4 个字节。

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

问题:

在可移植的 C 共享库中是否有针对基本类型的既定最佳实践?

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

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

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

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

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