From 837048b086fc40c34186cf6ebc4795780f35148b Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Fri, 17 Feb 2023 21:36:53 -0700 Subject: [PATCH] feat: add registerFns to 5.1 api This is for the luaL_register function --- src/ziglua-5.1/lib.zig | 41 ++++++++++++++++++++-------------------- src/ziglua-5.1/tests.zig | 30 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/ziglua-5.1/lib.zig b/src/ziglua-5.1/lib.zig index 2727896..cab0dc7 100644 --- a/src/ziglua-5.1/lib.zig +++ b/src/ziglua-5.1/lib.zig @@ -106,7 +106,7 @@ pub const Event = enum(u3) { /// Type for arrays of functions to be registered pub const FnReg = struct { name: [:0]const u8, - func: ?CFn, + func: CFn, }; /// The index of the global environment table @@ -1407,28 +1407,27 @@ pub const Lua = struct { } /// Opens a library - /// TODO: finish this function - // pub fn registerFns(lua: *Lua, libname: ?[:0]const u8, funcs: []const FnReg) void { - // if (libname) |name| { - // lua.findTable - // } - - // } - - /// Registers all functions in the array `fns` into the table on the top of the stack - /// All functions are created with `num_upvalues` upvalues - pub fn setFuncs(lua: *Lua, funcs: []const FnReg, num_upvalues: i32) void { - lua.checkStackAux(num_upvalues, "too many upvalues"); + pub fn registerFns(lua: *Lua, libname: ?[:0]const u8, funcs: []const FnReg) void { + // translated from the implementation of luaI_openlib so we can use a slice of + // FnReg without requiring a sentinel end value + if (libname) |name| { + _ = c.luaL_findtable(lua.state, registry_index, "_LOADED", 1); + lua.getField(-1, name); + if (!lua.isTable(-1)) { + lua.pop(1); + if (c.luaL_findtable(lua.state, globals_index, name, @intCast(c_int, funcs.len))) |_| { + lua.raiseErrorAux("name conflict for module " ++ c.LUA_QS, .{name.ptr}); + } + lua.pushValue(-1); + lua.setField(-3, name); + } + lua.remove(-2); + lua.insert(-1); + } for (funcs) |f| { - if (f.func) |func| { - var i: i32 = 0; - // copy upvalues to the top - while (i < num_upvalues) : (i += 1) lua.pushValue(-num_upvalues); - lua.pushClosure(func, num_upvalues); - } else lua.pushBoolean(false); // register a placeholder - lua.setField(-(num_upvalues + 2), f.name); + lua.pushFunction(f.func); + lua.setField(-2, f.name); } - lua.pop(num_upvalues); } /// Raises a type error for the argument `arg` of the C function diff --git a/src/ziglua-5.1/tests.zig b/src/ziglua-5.1/tests.zig index b0c07c5..62a8254 100644 --- a/src/ziglua-5.1/tests.zig +++ b/src/ziglua-5.1/tests.zig @@ -395,6 +395,36 @@ test "string buffers" { lua.pop(1); } +test "function registration" { + var lua = try Lua.init(testing.allocator); + defer lua.deinit(); + + // register all functions as part of a table + const funcs = [_]ziglua.FnReg{ + .{ .name = "add", .func = ziglua.wrap(add) }, + }; + lua.newTable(); + lua.registerFns(null, &funcs); + + lua.getField(-1, "add"); + lua.pushInteger(1); + lua.pushInteger(2); + try lua.protectedCall(2, 1, 0); + try expectEqual(@as(Integer, 3), lua.toInteger(-1)); + lua.setTop(0); + + // register functions as globals in a library table + lua.registerFns("testlib", &funcs); + + // testlib.add(1, 2) + lua.getGlobal("testlib"); + lua.getField(-1, "add"); + lua.pushInteger(1); + lua.pushInteger(2); + try lua.protectedCall(2, 1, 0); + try expectEqual(@as(Integer, 3), lua.toInteger(-1)); +} + test "panic fn" { var lua = try Lua.init(testing.allocator); defer lua.deinit();