@cImport
Writing every C declaration by hand is tedious. Zig can read C headers directly.
The usual form is:
const c = @cImport({
@cInclude("stdio.h");
});This creates a namespace named c. Declarations from the C header are available through that namespace.
A complete program:
const c = @cImport({
@cInclude("stdio.h");
});
pub fn main() void {
_ = c.puts("hello from C");
}Run it:
zig run main.zig -lcThe call:
c.puts("hello from C")uses the C function declared in stdio.h.
The return value is assigned to _ because puts returns an int, and Zig does not allow an ignored value unless the programmer says so.
@cImport may include more than one header:
const c = @cImport({
@cInclude("stdio.h");
@cInclude("stdlib.h");
@cInclude("string.h");
});It may also define macros before including a header:
const c = @cImport({
@cDefine("_GNU_SOURCE", {});
@cInclude("stdio.h");
});The block inside @cImport is not ordinary runtime code. It is evaluated by the compiler while translating C declarations into Zig declarations.
Header search paths are passed to the compiler:
zig build-exe main.zig -Iinclude -lcA header in include/foo.h can then be imported:
const c = @cImport({
@cInclude("foo.h");
});Use @cImport when the C API is large or when the declarations must track a real header file.
Use extern fn when the API is small and explicit declarations are clearer.