Hi !
I wanted to showcase one of my side project which was to wrap around the Lua API for Zig. I needed it for another personal project and in the end open-sourced my lua bindings. It uses the latest zig master branch.
I feel like I’ve done a good job at DX, optimization might not be the same I tried to minimize as much as possible allocations. So at runtime, the wrapper will free / allocate only what’s needed at the extra cost of walking through fields of structs etc.
The code is available here :
It was also an excuse to try out codeberg !
Here’s an example code :
// functions can take or return a struct as
// an argument !
fn functor(value: struct {
internal: u32
}) u32 {
std.log.debug("functor({})", .{value});
return value.internal * value.internal;
}
const LUA_PROGRAM =
\\function multiply(x, y)
\\ local z = x * y
\\ z = functor({ internal = z })
\\ return z
\\end
;
pub fn main(init: std.process.Init) !void {
var state: lua.Lua = try .init(init.gpa, .{});
defer state.deinit();
defer {
if (state.diag.hasErr()) {
std.log.err("{}: {s}", .{ state.diag.err.?, state.diag.message });
}
}
try state.setGlobal("functor", functor);
const reader = std.Io.Reader.fixed(LUA_PROGRAM);
try state.loadFromReader(reader);
// The program must be ran once to load symbols
try state.run();
// Return value (here `u32`) can be a struct, string, etc.
// If it is a string or a struct containing one, don't forget to call
// state.free(#) on it !
const ret = try state.call("multiply", .{ 2, 3 }, u32);
std.log.debug("functor(2 * 3) = {}", .{ret});
}