If I write a library with a C API but implemented in Zig, with a handwritten header file (necessary with -femit-h not working, but it might be preferable anyways to have a user-friendly header with comments etc. instead of something automatically generated), is there a way to check that the implementation in Zig matches the function prototypes of the header file?
If I implemented the library in C, I would simply #include the header file, and the compiler produce errors if something doesn’t match.
But in Zig, for example if the header file mathtest.h is
double add(double a, double b);
and the zig implementation is
const c = @cImport(@cInclude("mathtest.h")); // doesn't do anything
// definition for c.add (but the types are wrong!)
export fn add(a: f32, b: f32) f32 {
return a + b;
}
this gets compiled to a library and linked to a C program without errors, and just leads to undefined behavior at runtime.
Just a quick idea without having a compiler at hand.
In zig you should be able to compare the types of add and c.add. Place those comparisons in the first line of your exported functions and emit a @compileError if they do not match.
test "matches header" {
try @import("std").testing.expectEqual(@TypeOf(c.add), @TypeOf(add));
}
This indeed finds the mismatch (“expected type fn (f64, f64) callconv(.c) f64, found type fn (f32, f32) callconv(.c) f32”).
I would have to check every function though. Maybe it is possible to loop through all functions? But @typeInfo(@This()).@"struct".decls contains only the names of pub functions, and no types.