I’m writing some editor code with Zig cimgui bindings and am coming across many situations where passing values between Zig and C imgui API is kind of awkward.
In the below code, InputText
is declared as
fn inputText(label: ?[*:0]const u8, buf: ?[*]u8, buf_size: usize) bool
It makes sense to be passing null-terminated strings directly to cimgui rather than having some sort of conversion in the middle. However, code using this API ends up being kind of ugly and error prone, for example:
var buf: [256]u8 = undefined;
var curAsset = editor.selectedAsset();
_ = std.fmt.bufPrintZ(&buf, "{s}", .{curAsset.name}) catch unreachable;
if (imgui.InputText("Asset name", &buf, 256)) {
curAsset.setName(std.mem.sliceTo(&buf, 0), editor.allocator);
}
I’m thinking one reasonable pattern might be to declare some type such as CapacitySlice
which would allocate a fixed size buffer to hold a certain capacity so that the below code would be something like this instead:
var str = CapacitySlice(u8, 256).init(); // hold 256 bytes of space, string length = 0 after init
var curAsset = editor.selectedAsset();
// Note: can't pass "curAsset.name" directly to imgui because curAsset is a normal
// string slice "[]u8" and doesn't have enough capacity for storing the new edited
// name which InputText writes to its destination buffer.
_ = std.fmt.bufPrintZ(&str.ptr(), "{s}", .{curAsset.name}) catch unreachable;
if (imgui.InputText_Slice("Asset name", str)) {
curAsset.setName(std.mem.sliceTo(&buf, 0), editor.allocator);
}
Little like std.ArrayList
except with a fixed size allocation.
Does this approach make sense or might there be a nicer/cleaner/more idiomatic way to do this? Or maybe there are already some useful types for this in the standard library?