NUS Hackers Wiki
NUS Hackers Wiki
  • NUS Hackers Wiki
  • Hackerschool
    • Virtual Machines and Linux
    • Beginners' Guide to the Terminal
      • Introduction to the Terminal
      • Modern Shell Tools
      • Shell Scripting
      • Real World Scripting
      • Resources
    • Self-Hosting: Three Easy Pieces
      • 1. Setting up your server
      • 2. Running Services
      • 3. Monitoring your server
    • Vim
    • Introduction to Zig
      • Language Basics
      • Error Handling
      • Memory Management
      • Working with C
      • Exploring comptime
    • CI/CD with Github Actions
      • Background
      • Basics of Github Actions
        • Target workflow
        • Running unit tests
        • Linting code
        • Deploying to Github Pages
      • Advanced use cases
        • Pollers
        • Github script
        • Executing third-party scripts
        • Reusable workflows
      • Cookbook
    • Lightning Git
      • Git Concepts
      • Getting Started with Git
      • Making your first commit
      • Branching
      • Merge Conflicts
      • Integrating remote repositories
      • Collaborative Workflows
      • Commit Manipulation and Reflog
      • Interactive rebasing
      • filter-repo
  • Orbital
    • JavaScript
      • Browser Developer Tools
      • Getting Started
      • Datatypes
      • Operators and Operations
      • Loops and Conditions
      • Functions
      • Strings
      • Arrays
      • HTML
        • Getting Started
        • Tag Attributes
        • HTML Forms
        • Browser Inspector
      • CSS
        • Selectors
        • Colors in CSS
        • Measurements in CSS
        • The Box Model
        • Adding Styles - Part 1
        • Adding Styles - Part 2
      • Working with the DOM
        • Querying the DOM - Selectors
        • Querying the DOM - Element Attributes
        • Querying the DOM - Element Styles
        • Events with JS and HTML
        • Exercise: Click Counter
        • Editing the DOM
        • Fetch Requests
        • Exercise: The NUSMods API
    • React
      • Setup
      • State
    • React Native
      • Setup
      • Intro to JSX
      • Basic Syntax
      • Handling UI
      • Props
      • State Management
    • Git
      • Setup
      • Command Glossary
      • Fundamental Concepts
        • Getting Started
        • Integrating Remote Repositories
        • Branching
        • Merge Conflicts
      • Collaborative Workflows
        • Fork and PR Workflow
        • Branch and PR Workflow
      • Advanced Concepts
        • Ignoring Files
        • Commit Message Conventions
        • Github Collaborators
        • CI/CD with Github Actions
        • Advanced Git Commands
      • FAQ
    • Telegram Bot
      • Creating a TeleBot
      • API Calls
      • Telebot Basics
      • Integrating API's
    • Relational Database
      • Database Overview
      • Database Design
      • Entity Relationship Diagram
      • SQL Basics & PostgreSQL
    • TypeScript
      • Types and Interfaces
      • Utility Types
      • Typing Component Props, Events, and Hooks
      • Why You Should Avoid Using any (and What to Do Instead)
      • TypeScript Tricks You’ll Use All the Time in React
Powered by GitBook
On this page
Edit on GitHub
Export as PDF
  1. Hackerschool
  2. Introduction to Zig

Working with C

One of the great features of Zig is that it is fully compatible with C. Let's return to the Hello, world! example, this time using C to print instead of Zig.

const c = @cImport({
    @cInclude("stdio.h");
});

pub fn main() !void {
    _ = c.printf("Hello, world!\n");
}

That's it! Using the cImport directive, we can directly use C code inside of Zig. Of course, please compile this to verify that it works as expected.

For the rest of this page, we'll be working across multiple files. The filenames will be given in a comment that precedes the source code. Creating a new directory to store all these source files is encouraged, so that it doesn't get too messy.

Custom C code

Let's write some of our own code instead of using the C standard library. Our custom C program will have just a single greet function, that says hello to the name passed as a parameter.

// In file /c-src/greeter.h

void greet(const char *name);

// In file /c-src/greeter.c

#include "greeter.h"
#include <stdio.h>

void greet(const char *name) {
  if (name == NULL) {
    printf("Hello, world!\n");
  } else {
    printf("Hello, %s!\n", name);
  }
}

Let's verify that this works as a C program first. We can create a temporary main file for the C program.

// In file /c-src/main.c

#include "greeter.h"
#include <stdio.h>

int main() {
  greet("Alice");
  greet("Bob");
  greet(NULL);
  return 0;
}

And then compile it using gcc as with any other C program.

$ gcc -o greet c-src/greeter.c c-src/main.c  
$ ./greet
Hello, Alice!
Hello, Bob!
Hello, world!

It works! So how do we get gcc to work with Zig? Ah! We unveil the secret behind Zig's ability to handle C code so well. It comes with a C compiler :O

$ zig cc -o greet c-src/greeter.c c-src/main.c  
$ ./greet
Hello, Alice!
Hello, Bob!
Hello, world!

Insane! Let's continue by trying using this C code in Zig instead of just C. We can start by modifying our build file to look for greeter.h in the correct place.

// In file /build.zig

const std = @import("std");

pub fn build(b: *std.Build) void {
    const exe = b.addExecutable(.{
        .name = "greet",
        .root_source_file = b.path("src/main.zig"),
        .target = b.standardTargetOptions(.{}),
        .optimize = b.standardOptimizeOption(.{}),
    });
    exe.addIncludePath(b.path("c-src"));

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}

Now, we can configure our main.zig file to import our custom greeter.c.

// In file /src/main.zig

const c = @cImport({
    @cInclude("greeter.c");
});

pub fn main() !void {
    c.greet("Alice");
    c.greet("Bob");
    c.greet(null);
}

We use the zig build run command instead of zig run, and we can see that everything works well!

$ zig build run
Hello, Alice!
Hello, Bob!
Hello, world!

PreviousMemory ManagementNextExploring comptime

Last updated 2 months ago

Okay, if you're cheeky and try doing zig cc --help, you might discover that it's actually Clang (on a Macbook at least). But the creator of Zig actually , and TL;DR it is Clang but smaller and does more out-of-the-box.

wrote about this