代码范例

← 返回

学习

代码范例

Hello world调用外部库函数内存泄露检测C 互操作性Zigg Zagg泛型在 Zig 中使用 cURL

Hello worldA minimal example printing hello world.

hello-world.zigconst std = @import("std");

pub fn main() !void {

const stdout = std.io.getStdOut().writer();

try stdout.print("hello world!\n", .{});

}Shell$ zig build-exe hello-world.zig

$ ./hello-world

hello world!

调用外部库函数所有的系统 API 函数都可以通过这种方式调用,您不需要库绑定来与它们交互。

windows-msgbox.zigconst win = @import("std").os.windows;

extern "user32" fn MessageBoxA(?win.HWND, [*:0]const u8, [*:0]const u8, u32) callconv(win.WINAPI) i32;

pub fn main() !void {

_ = MessageBoxA(null, "world!", "Hello", 0);

}Shell$ zig test windows-msgbox.zig

All 0 tests passed.

内存泄露检测使用 std.heap.GeneralPurposeAllocator 来检测双重释放和内存泄露。

memory-leak.zigconst std = @import("std");

pub fn main() !void {

var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};

defer std.debug.assert(general_purpose_allocator.deinit() == .ok);

const gpa = general_purpose_allocator.allocator();

const u32_ptr = try gpa.create(u32);

_ = u32_ptr; // silences unused variable error

// oops I forgot to free!

}Shell$ zig build-exe memory-leak.zig

$ ./memory-leak

error(gpa): memory address 0x7ff322440000 leaked:

/home/ci/actions-runner-website/_work/www.ziglang.org/www.ziglang.org/zig-code/samples/memory-leak.zig:9:35: 0x10e0237 in main (memory-leak)

const u32_ptr = try gpa.create(u32);

^

/home/ci/deps/zig-linux-x86_64-0.14.0/lib/std/start.zig:656:37: 0x10e010a in posixCallMainAndExit (memory-leak)

const result = root.main() catch |err| {

^

/home/ci/deps/zig-linux-x86_64-0.14.0/lib/std/start.zig:271:5: 0x10dfcbd in _start (memory-leak)

asm volatile (switch (native_arch) {

^

thread 1954844 panic: reached unreachable code

/home/ci/deps/zig-linux-x86_64-0.14.0/lib/std/debug.zig:522:14: 0x104ae2d in assert (memory-leak)

if (!ok) unreachable; // assertion failure

^

/home/ci/actions-runner-website/_work/www.ziglang.org/www.ziglang.org/zig-code/samples/memory-leak.zig:5:27: 0x10e02b5 in main (memory-leak)

defer std.debug.assert(general_purpose_allocator.deinit() == .ok);

^

/home/ci/deps/zig-linux-x86_64-0.14.0/lib/std/start.zig:656:37: 0x10e010a in posixCallMainAndExit (memory-leak)

const result = root.main() catch |err| {

^

/home/ci/deps/zig-linux-x86_64-0.14.0/lib/std/start.zig:271:5: 0x10dfcbd in _start (memory-leak)

asm volatile (switch (native_arch) {

^

???:?:?: 0x0 in ??? (???)

(process terminated by signal)

C 互操作性导入 C 头文件并链接到 libc 和 raylib 的示例。

c-interop.zig// 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 ZaggZig 已为代码面试做了优化(并没有)。

ziggzagg.zigconst 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});

}

}

}Shell$ zig build-exe ziggzagg.zig

$ ./ziggzagg

1

2

Zigg

4

Zagg

Zigg

7

8

Zigg

Zagg

11

Zigg

13

14

ZiggZagg

16

泛型在 Zig 中,类型是编译期的值,我们使用返回类型的函数来实现泛型算法和数据结构。在此示例中,我们实现了一个简单的泛型队列并测试其行为。

generic-type.zigconst std = @import("std");

pub fn Queue(comptime Child: type) type {

return struct {

const Self = @This();

const Node = struct {

data: Child,

next: ?*Node,

};

gpa: std.mem.Allocator,

start: ?*Node,

end: ?*Node,

pub fn init(gpa: std.mem.Allocator) Self {

return Self{

.gpa = gpa,

.start = null,

.end = null,

};

}

pub fn enqueue(self: *Self, value: Child) !void {

const node = try self.gpa.create(Node);

node.* = .{ .data = value, .next = null };

if (self.end) |end| end.next = node //

else self.start = node;

self.end = node;

}

pub fn dequeue(self: *Self) ?Child {

const start = self.start orelse return null;

defer self.gpa.destroy(start);

if (start.next) |next|

self.start = next

else {

self.start = null;

self.end = null;

}

return start.data;

}

};

}

test "queue" {

var int_queue = Queue(i32).init(std.testing.allocator);

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);

}Shell$ zig test generic-type.zig

1/1 generic-type.test.queue...OK

All 1 tests passed.

在 Zig 中使用 cURL

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();

const allocator = arena_state.allocator();

// global curl init, or fail

if (cURL.curl_global_init(cURL.CURL_GLOBAL_ALL) != cURL.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, cURL.CURLOPT_URL, "https://ziglang.org") != cURL.CURLE_OK)

return error.CouldNotSetURL;

// set write function callbacks

if (cURL.curl_easy_setopt(handle, cURL.CURLOPT_WRITEFUNCTION, writeToArrayListCallback) != cURL.CURLE_OK)

return error.CouldNotSetWriteCallback;

if (cURL.curl_easy_setopt(handle, cURL.CURLOPT_WRITEDATA, &response_buffer) != cURL.CURLE_OK)

return error.CouldNotSetWriteCallback;

// perform

if (cURL.curl_easy_perform(handle) != cURL.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: *anyopaque, size: c_uint, nmemb: c_uint, user_data: *anyopaque) callconv(.C) c_uint {

var buffer: *std.ArrayList(u8) = @alignCast(@ptrCast(user_data));

var typed_data: [*]u8 = @ptrCast(data);

buffer.appendSlice(typed_data[0 .. nmemb * size]) catch return 0;

return nmemb * size;

}