Changes
1 changed files (+47/-49)
-
-
@@ -19,23 +19,7 @@# core Clients use this module and renders state struct managed by this. Actions are modeled as function returning `void` and clients listen to changes to the state via event callbacks. ```c // Sample definition: // This dispatches an action without waiting for a result. void plac_play_song(plac_app*, plac_song*); // First argument is event payload and second argument is context/user data. typedef void (*plac_cb_playback_change)(plac_song*, void*); // The last argument is context/user data, which will be passed to the callback. void plac_on_playback_change(plac_app*, plac_cb_playback_change, void*); // Events without payload have the following signature. typedef void (*plac_cb_foo)(void*); ``` Every function is blocking, so client is responsible for making them asynchronous. ## Code Styles
-
@@ -52,61 +36,75 @@This is what many Zig projects, including `std`, uses. Let the caller decide where to store. An exported function (C API) should wrap `init` function and assign the result to an allocated space. ```zig const std = @import("std"); extern struct Foo { pub const Foo = struct { bar: i32, pub fn init() Foo { return .{ bar = 0 }; } pub fn make() callconv(.C) ?*Foo { const dst = std.heap.c_allocator.create(Foo) catch return null; dst.* = init(); return dst; } } comptime { @export(&Foo.make, .{ .name = "plac_foo_make" }); } ``` ### Struct destroy function A function that releases resources owned by `struct Foo`, ### Struct creation and allocation function - should be named `deinit` - should return `void` - should not return an error union - should not destroy a pointer to itself A function that allocates and initializes `struct Foo`, An exported function (C API) should wrap `deinit` function and free the pointer to itself. - should be named `make` - should return a pointer (`*Foo`) - should NOT take an allocator - can return an error union ```zig const std = @import("std"); extern struct Foo { pub fn deinit(self: *const Foo) void { // ... } pub const Foo = extern struct { const allocator = std.heap.c_allocator; pub fn free(self_ptr: ?*const Foo) callconv(.C) void { const self = self_ptr orelse return; self.deinit(); std.heap.c_allocator.destroy(self); bar: i32, pub fn make() callconv(.C) std.mem.Allocator.Error!*Foo { const dst = try allocator.create(Foo); dst.* = .{ .bar = 0, }; return dst; } } comptime { @export(&Foo.free, .{ .name = "plac_foo_free" }); @export(&Foo.make, .{ .name = "plac_foo_make" }); } ``` ### Exported struct internal Exported structs' initial field must be a pointer to an internal struct: ```c // plac.h typedef struct { void *__pri; uint32_t bar; } plac_foo; ``` ```zig // foo.zig pub const Foo = extern struct { internal: *Internal, bar: u32, const Internal = struct { baz: u32, }; }; ``` Non-ABI stable fields (e.g. slices, reference counter) and internal fields should go inside `internal` field. ### Function parameters Zig team has a plan to drop automatic pass-by-reference conversion for function parameters.
-
@@ -114,7 +112,7 @@ To minimize the cost of future migration, do not annotate a parameter with value type if pass-by-value is not desirable.For this reason, struct methods should use pointer type for `self` parameter. ```zig struct Foo { pub const Foo = struct { // OK pub fn bar(self: *Foo): void {}
-
@@ -131,7 +129,7 @@When an exported function takes a pointer, it should be an optional pointer rather than regular pointer, to guard against accidentally passing NULL pointer. ```zig extern struct Foo { pub const Foo = extern struct { pub fn bar(self: *const Foo) void { // ... }
-