🎓 A1Learner
🔍
0 of 46 lessons completed

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?