Using C

One of Zig’s strengths is that it makes it easy to call libraries written in C. Let’s start with a program that prints Hello World using the printf function.

We start with a C header file that includes the definitions we need:

/* hello.h */
#include <stdio.h>

Next, we need a build.zig to tell Zig how to build the C and Zig source files:

const std = @import("std");

pub fn build(b: *std.Build) void {
    const root_source_file = b.path("hello.zig");

    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // We’re telling Zig to compile our C header,
    const translate_c = b.addTranslateC(.{
        .root_source_file = b.path("hello.h"),
        .target = target,
        .optimize = optimize,
    });
    // turn it into a Zig module,
    const c_module = translate_c.createModule();

    const exe = b.addExecutable(.{
        .name = "hello",
        .root_module = b.createModule(.{
            .root_source_file = root_source_file,
            .target = target,
            .optimize = optimize,
            // and make it available to import in Zig.
            .imports = &.{
                .{
                    .name = "c",
                    .module = c_module,
                },
            },
        }),
    });
    b.installArtifact(exe);

    const run_step = b.step("run", "Run the program");
    const run_exe = b.addRunArtifact(exe);
    run_step.dependOn(&run_exe.step);
}

We’ve made the contents of hello.h available under the name c, so we can import it with @import("c"):

const c = @import("c");

pub fn main() void {
    // We call `printf` like any other function. It
    // returns the number of bytes printed, which we
    // ignore here.
    _ = c.printf("Hello, world!\n");
}
$ zig build run
Hello, world!

Next example: C Types.