أمثلة

كشف تسرب الذاكرة

باستخدام std.heap.GeneralPurposeAllocator يمكنك تتبُع التحريرات المزدوجة وتسريبات الذاكرة.

leak.zig

const std = @import("std");

pub fn main() !void {
    var gpalloc = std.heap.GeneralPurposeAllocator(.{}){};
    defer std.debug.assert(!gpalloc.deinit());

    const alloc = &gpalloc.allocator;

    const u32_ptr = try alloc.create(u32);
    _ = u32_ptr; // silences unused variable error

    // oops I forgot to free!
}
$ zig build-exe leak.zig
$ ./leak
error(gpa): memory address 0x7f05187a4000 leaked: 
/home/runner/work/www.ziglang.org/www.ziglang.org/doctest-884cf22a/leak.zig:9:37: 0x22a5d4 in main (leak)
    const u32_ptr = try alloc.create(u32);
                                    ^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:527:37: 0x222d4a in std.start.callMain (leak)
            const result = root.main() catch |err| {
                                    ^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:469:12: 0x206dae in std.start.callMainWithArgs (leak)
    return @call(.{ .modifier = .always_inline }, callMain, .{});
           ^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:383:17: 0x205e36 in std.start.posixCallMainAndExit (leak)
    std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
                ^


thread 3326 panic: reached unreachable code
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/debug.zig:226:14: 0x204ebb in std.debug.assert (leak)
    if (!ok) unreachable; // assertion failure
             ^
/home/runner/work/www.ziglang.org/www.ziglang.org/doctest-884cf22a/leak.zig:5:27: 0x22a64c in main (leak)
    defer std.debug.assert(!gpalloc.deinit());
                          ^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:527:37: 0x222d4a in std.start.callMain (leak)
            const result = root.main() catch |err| {
                                    ^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:469:12: 0x206dae in std.start.callMainWithArgs (leak)
    return @call(.{ .modifier = .always_inline }, callMain, .{});
           ^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:383:17: 0x205e36 in std.start.posixCallMainAndExit (leak)
    std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
                ^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:296:5: 0x205c42 in std.start._start (leak)
    @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
    ^
(process terminated by signal)

التوافق مع C

مثال لتوريد ملف تعريفي بلغة الـC وربط مكتبات libc وraylib.

// build with `zig build-exe cimport.zig -lc -lraylib`
const ray = @cImport({
    @cInclude("raylib.h");
});

pub fn main() void {
    const screenWidth = 800;
    const screenHeight = 450;

    ray.InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
    defer ray.CloseWindow();

    ray.SetTargetFPS(60);

    while (!ray.WindowShouldClose()) {
        ray.BeginDrawing();
        defer ray.EndDrawing();

        ray.ClearBackground(ray.RAYWHITE);
        ray.DrawText("Hello, World!", 190, 200, 20, ray.LIGHTGRAY);
    }
}

Zigg Zagg

صممت Zig لأسئلة اختبارات البرمجة (غير صحيح).

zag.zig

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    var i: usize = 1;
    while (i <= 16) : (i += 1) {
        if (i % 15 == 0) {
            try stdout.writeAll("ZiggZagg\n");
        } else if (i % 3 == 0) {
            try stdout.writeAll("Zigg\n");
        } else if (i % 5 == 0) {
            try stdout.writeAll("Zagg\n");
        } else {
            try stdout.print("{d}\n", .{i});
        }
    }
}
$ zig build-exe zag.zig
$ ./zag
1
2
Zigg
4
Zagg
Zigg
7
8
Zigg
Zagg
11
Zigg
13
14
ZiggZagg
16

الأنواع العامة

الأنواع في Zig هي قيم معروفة في زمن التصريف ويمكننا استخدام وظائف ترجع أنواع لتنفيذ خوارزميات عامة وهيكلة البيانات. في هذا المثال سنقوم بتنفيذ صف (queue) عام مٌبسّط وسنختبره.

queue.zig

const std = @import("std");

pub fn Queue(comptime Child: type) type {
    return struct {
        const This = @This();
        const Node = struct {
            data: Child,
            next: ?*Node,
        };
        alloc: *std.mem.Allocator,
        start: ?*Node,
        end: ?*Node,

        pub fn init(alloc: *std.mem.Allocator) This {
            return This{
                .alloc = alloc,
                .start = null,
                .end = null,
            };
        }
        pub fn enqueue(this: *This, value: Child) !void {
            const node = try this.alloc.create(Node);
            node.* = .{ .data = value, .next = null };
            if (this.end) |end| end.next = node //
            else this.start = node;
            this.end = node;
        }
        pub fn dequeue(this: *This) ?Child {
            const start = this.start orelse return null;
            defer this.alloc.destroy(start);
            if (start.next) |next|
                this.start = next
            else {
                this.start = null;
                this.end = null;
            }
            return start.data;
        }
    };
}

test "queue" {
    const alloc = std.testing.allocator;

    var int_queue = Queue(i32).init(alloc);

    try int_queue.enqueue(25);
    try int_queue.enqueue(50);
    try int_queue.enqueue(75);
    try int_queue.enqueue(100);

    try std.testing.expectEqual(int_queue.dequeue(), 25);
    try std.testing.expectEqual(int_queue.dequeue(), 50);
    try std.testing.expectEqual(int_queue.dequeue(), 75);
    try std.testing.expectEqual(int_queue.dequeue(), 100);
    try std.testing.expectEqual(int_queue.dequeue(), null);

    try int_queue.enqueue(5);
    try std.testing.expectEqual(int_queue.dequeue(), 5);
    try std.testing.expectEqual(int_queue.dequeue(), null);
}
$ zig test queue.zig
Test [1/1] test "queue"... 
All 1 tests passed.

استخدام cURL من Zig

// compile with `zig build-exe zig-curl-test.zig --library curl --library c $(pkg-config --cflags libcurl)`
const std = @import("std");
const cURL = @cImport({
    @cInclude("curl/curl.h");
});

pub fn main() !void {
    var arena_state = std.heap.ArenaAllocator.init(std.heap.c_allocator);
    defer arena_state.deinit();
    var allocator = &arena_state.allocator;

    // global curl init, or fail
    if (cURL.curl_global_init(cURL.CURL_GLOBAL_ALL) != .CURLE_OK)
        return error.CURLGlobalInitFailed;
    defer cURL.curl_global_cleanup();

    // curl easy handle init, or fail
    const handle = cURL.curl_easy_init() orelse return error.CURLHandleInitFailed;
    defer cURL.curl_easy_cleanup(handle);

    var response_buffer = std.ArrayList(u8).init(allocator);

    // superfluous when using an arena allocator, but
    // important if the allocator implementation changes
    defer response_buffer.deinit();

    // setup curl options
    if (cURL.curl_easy_setopt(handle, .CURLOPT_URL, "https://ziglang.org") != .CURLE_OK)
        return error.CouldNotSetURL;

    // set write function callbacks
    if (cURL.curl_easy_setopt(handle, .CURLOPT_WRITEFUNCTION, writeToArrayListCallback) != .CURLE_OK)
        return error.CouldNotSetWriteCallback;
    if (cURL.curl_easy_setopt(handle, .CURLOPT_WRITEDATA, &response_buffer) != .CURLE_OK)
        return error.CouldNotSetWriteCallback;

    // perform
    if (cURL.curl_easy_perform(handle) != .CURLE_OK)
        return error.FailedToPerformRequest;

    std.log.info("Got response of {d} bytes", .{response_buffer.items.len});
    std.debug.print("{s}\n", .{response_buffer.items});
}

fn writeToArrayListCallback(data: *c_void, size: c_uint, nmemb: c_uint, user_data: *c_void) callconv(.C) c_uint {
    var buffer = @intToPtr(*std.ArrayList(u8), @ptrToInt(user_data));
    var typed_data = @intToPtr([*]u8, @ptrToInt(data));
    buffer.appendSlice(typed_data[0 .. nmemb * size]) catch return 0;
    return nmemb * size;
}