Zig C Linking
C linking is the step that connects a Zig program to the C library so its functions can run. The build file records that connection, and the program then calls C functions normally.
Link the C library in a build file
The build file links the C library for the executable. The program then calls a C function and prints the result.
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "clink",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
exe.linkLibC();
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
b.step("run", "Run the app").dependOn(&run_cmd.step);
}
Declare one C function directly
An extern declaration names the absolute value function without a header import. The program prints the absolute value of negative twelve.
const std = @import("std");
extern fn abs(x: c_int) c_int;
pub fn main() !void {
const v = abs(-12);
const out = std.io.getStdOut().writer();
try out.print("abs={d}\n", .{v});
}
A long absolute value
The standard library header also declares a long version of absolute value. Zig prints the converted result for a negative input.
const std = @import("std");
const c = @cImport({
@cInclude("stdlib.h");
});
pub fn main() !void {
const v = c.labs(-12345);
const out = std.io.getStdOut().writer();
try out.print("labs={d}\n", .{v});
}
Example
const std = @import("std");
const c = @cImport({
@cInclude("stdlib.h");
@cInclude("string.h");
});
pub fn main() !void {
const a = c.abs(-3);
const len = c.strlen("zig!");
const out = std.io.getStdOut().writer();
try out.print("abs={d} len={d}\n", .{ a, len });
}
Key points
- Linking: linking is the step that connects compiled code to a library it calls.
- C library: the C library is the standard collection of C functions supplied with the system.
- The build file links the C library with one call, and every C function in the program then resolves.
- A run block links the same library with the -lc flag instead of a build file.
- An extern declaration names a C function directly, without importing a header.
- The program still checks return values from C functions, since linking alone does not make a call succeed.
The example imports the standard library and string headers. It takes the absolute value of negative three and the length of a four-letter word. It prints both results after both calls return.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Where does a build file record the connection to the C library?