├── .gitignore ├── README.md ├── build.zig └── src ├── main.zig └── vendor ├── include └── my.h ├── myadd.c └── mytime.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | zig-cache/ 3 | zig-out/ 4 | *~ 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `Zig` with `C` 2 | This is a very simple example to demonstrate how `Zig` works with `C`. 3 | 4 | # Run 5 | Use below script to run. 6 | ```bash 7 | zig build run 8 | ``` 9 | 10 | # Test 11 | Use below script to test. 12 | ```bash 13 | zig build test 14 | ``` 15 | 16 | # The magic 17 | It's in `build.zig`, the magic code is here. 18 | *(You may change or add more flags in `c_args`.)* 19 | 20 | ```zig 21 | fn withC(exe: *std.build.LibExeObjStep) void { 22 | const c_args = [_][]const u8{ 23 | "-std=c99", 24 | }; 25 | 26 | exe.linkLibC(); 27 | exe.addIncludePath("src/vendor/include"); 28 | exe.addCSourceFile("src/vendor/myadd.c", &c_args); 29 | exe.addCSourceFile("src/vendor/mytime.c", &c_args); 30 | } 31 | ``` 32 | 33 | Invoking the function `withC` for `zig build run`, 34 | ```zig 35 | ... 36 | const exe = b.addExecutable("zigwithc", "src/main.zig"); 37 | exe.setTarget(target); 38 | exe.setBuildMode(mode); 39 | withC(exe); 40 | ... 41 | ``` 42 | and ` zig build test`. 43 | ```zig 44 | ... 45 | const exe_tests = b.addTest("src/main.zig"); 46 | exe_tests.setTarget(target); 47 | exe_tests.setBuildMode(mode); 48 | withC(exe_tests); 49 | ... 50 | ``` 51 | That's it. 52 | -------------------------------------------------------------------------------- /build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.build.Builder) void { 4 | // Standard target options allows the person running `zig build` to choose 5 | // what target to build for. Here we do not override the defaults, which 6 | // means any target is allowed, and the default is native. Other options 7 | // for restricting supported target set are available. 8 | const target = b.standardTargetOptions(.{}); 9 | 10 | // Standard release options allow the person running `zig build` to select 11 | // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. 12 | const mode = b.standardReleaseOptions(); 13 | 14 | const exe = b.addExecutable("zigwithc", "src/main.zig"); 15 | exe.setTarget(target); 16 | exe.setBuildMode(mode); 17 | withC(exe); 18 | exe.install(); 19 | 20 | const run_cmd = exe.run(); 21 | run_cmd.step.dependOn(b.getInstallStep()); 22 | if (b.args) |args| { 23 | run_cmd.addArgs(args); 24 | } 25 | 26 | const run_step = b.step("run", "Run the app"); 27 | run_step.dependOn(&run_cmd.step); 28 | 29 | const exe_tests = b.addTest("src/main.zig"); 30 | exe_tests.setTarget(target); 31 | exe_tests.setBuildMode(mode); 32 | withC(exe_tests); 33 | 34 | const test_step = b.step("test", "Run unit tests"); 35 | test_step.dependOn(&exe_tests.step); 36 | } 37 | 38 | fn withC(exe: *std.build.LibExeObjStep) void { 39 | const c_args = [_][]const u8{ 40 | "-std=c99", 41 | }; 42 | 43 | exe.linkLibC(); 44 | exe.addIncludePath("src/vendor/include"); 45 | exe.addCSourceFile("src/vendor/myadd.c", &c_args); 46 | exe.addCSourceFile("src/vendor/mytime.c", &c_args); 47 | } 48 | -------------------------------------------------------------------------------- /src/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const print = std.debug.print; 3 | 4 | const withc = @cImport({ 5 | @cInclude("my.h"); 6 | }); 7 | 8 | pub fn main() void { 9 | const val = zigAdd(1, 2); 10 | print("result is {}\n", .{val}); 11 | } 12 | 13 | fn zigAdd(a: i32, b: i32) i32 { 14 | return withc.add(a, b); 15 | } 16 | 17 | test "zig with c test" { 18 | const t = std.testing; 19 | try t.expectEqual(@intCast(i32, 8), zigAdd(3, 5)); 20 | } 21 | -------------------------------------------------------------------------------- /src/vendor/include/my.h: -------------------------------------------------------------------------------- 1 | int add(int a, int b); 2 | 3 | void getDateAndTime(char *buf); 4 | -------------------------------------------------------------------------------- /src/vendor/myadd.c: -------------------------------------------------------------------------------- 1 | #include "my.h" 2 | 3 | int add(int a, int b) 4 | { 5 | char buf[32]; 6 | getDateAndTime(buf); 7 | printf("[%s] calling c add with: a=%d, b=%d \n", buf, a, b); 8 | 9 | return a + b; 10 | } 11 | -------------------------------------------------------------------------------- /src/vendor/mytime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "my.h" 4 | 5 | void getDateAndTime(char *buf) 6 | { 7 | time_t now = time(NULL); 8 | struct tm l = *localtime(&now); 9 | sprintf(buf, "%02d-%02d-%02d %02d:%02d:%02d", l.tm_year + 1900, l.tm_mon + 1, l.tm_mday, l.tm_hour, l.tm_min, l.tm_sec); 10 | } 11 | --------------------------------------------------------------------------------