Skip to content

Commit cdd78ad

Browse files
committed
Add fnRegsFromStruct for comptime-generation of Lua function registrations
1 parent 31d1abd commit cdd78ad

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

src/lib.zig

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5408,3 +5408,38 @@ pub fn exportFn(comptime name: []const u8, comptime func: anytype) CFn {
54085408
}
54095409
}.luaopen;
54105410
}
5411+
5412+
/// Generates a list of Lua function registrations (`FnReg`) from all
5413+
/// pub declarations in a struct type `T`.
5414+
///
5415+
/// Example:
5416+
///
5417+
/// ```zig
5418+
/// const MyLib = struct {
5419+
/// fn someHelper(...) { ... } // non-pub funcs skipped
5420+
/// pub fn foo(l: *Lua) void { ... }
5421+
/// pub fn bar(l: *Lua) void { ... }
5422+
///
5423+
/// };
5424+
///
5425+
/// const funcs = fnRegsFromStruct(MyLib);
5426+
/// lua.newLib(funcs);
5427+
/// lua.setGlobal("mylib"); // mylib.foo, mylib.bar now visible
5428+
/// ```
5429+
pub inline fn fnRegsFromStruct(comptime T: type) []const FnReg {
5430+
comptime {
5431+
const decls = switch (@typeInfo(T)) {
5432+
.@"struct" => |info| info.decls,
5433+
else => @compileError("Expected struct, found '" ++ @typeName(T) ++ "'"),
5434+
};
5435+
var funcs: [decls.len]FnReg = undefined;
5436+
for (decls, 0..) |d, i| {
5437+
funcs[i] = .{
5438+
.name = d.name,
5439+
.func = wrap(@field(T, d.name)),
5440+
};
5441+
}
5442+
const final = funcs;
5443+
return &final;
5444+
}
5445+
}

src/tests.zig

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3093,3 +3093,29 @@ test "checkNumeric and toNumeric" {
30933093
_ = std.mem.indexOf(u8, string, error_msg) orelse return error.BadErrorMessage;
30943094
}
30953095
}
3096+
3097+
test "function registration with fnRegsFromStruct" {
3098+
const lua: *Lua = try .init(testing.allocator);
3099+
defer lua.deinit();
3100+
3101+
const MyLib = struct {
3102+
pub fn add(l: *Lua) i32 {
3103+
const a = l.toInteger(1) catch 0;
3104+
const b = l.toInteger(2) catch 0;
3105+
l.pushInteger(a + b);
3106+
return 1;
3107+
}
3108+
pub fn neg(l: *Lua) i32 {
3109+
const a = l.toInteger(1) catch 0;
3110+
l.pushInteger(-a);
3111+
return 1;
3112+
}
3113+
};
3114+
3115+
// Construct function registration table at comptime from
3116+
// public decls on MyLib.
3117+
lua.newLib(zlua.fnRegsFromStruct(MyLib));
3118+
lua.setGlobal("fnregs");
3119+
try lua.doString("res = fnregs.add(100, fnregs.neg(25))");
3120+
try expectEqual(75, lua.get(i32, "res"));
3121+
}

0 commit comments

Comments
 (0)