Problem:
Recently we've encountered the following problem with our C shared library.
The library defines a method like this one:
typedef enum {A, B, C} some_enum;
typedef struct {some_enum e; time_t t; char* data;} request;
void f(request);
We've compiled the library for multiple architectures using clang and its cross-compilation features. One of the platforms was Windows 32 bits.
And here is the problem: when trying to use the library in an example that uses MSVC 32-bit compiler, the example fails with seg fault.
The reason: in MSVC 32-bit time_t
is 8 bytes while in clang compilation for Windows 32-bits it is assumed to be 4 bytes.
Obviously, if we were using fixed-width integer types such as int64_t
, this problem would never appear.
Question:
Are there established best practices for primitive types in a portable C shared library?
For instance, is it the best practice to avoid any non fixed-width integer types altogether in C shared library interfaces?
Are for example enum
s "allowed" (in terms of best practices) in a portable C library?
Typically all compilers for a given platform try very hard to preserve the default C ABI. Violation of ABI is normally considered a compiler bug.
C++ ABI is trickier for various reasons but at least Clang tries hard to preserve that one on Windows as well.
C ABI compatibility means, among other things, that all primitive types have defined size and alignment so there is no need to use fixed-width types (i.e. long
will be the same for all compilers for a particular target).
As for your case, I suspect that clang and cl.exe are using different time.h
for whatever reason so I suggest to look into that (see my comment above on how to proceed with this).