Skip to content

Commit a3b5ab2

Browse files
committed
Allow *Lua receiver as first function param
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
1 parent e151c01 commit a3b5ab2

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

src/stack.zig

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,16 +277,26 @@ pub fn pushResult(lua: Lua, result: anytype) c_int {
277277
/// Creates a Lua C function from a Zig function.
278278
fn createFunc(_: Lua, value: anytype) State.CFunction {
279279
const T = @TypeOf(value);
280+
const arg_tuple = std.meta.ArgsTuple(T);
281+
const arg_fields = std.meta.fields(arg_tuple);
280282

281283
return struct {
282284
fn f(state: ?State.LuaState) callconv(.C) c_int {
283285
const l = Lua.fromState(state.?);
284286

285287
// Push func arguments
286288
// See https://www.lua.org/pil/26.1.html
287-
var args: std.meta.ArgsTuple(T) = undefined;
288-
inline for (std.meta.fields(std.meta.ArgsTuple(T)), 0..) |field, i| {
289-
args[i] = checkArg(l, i + 1, field.type);
289+
var args: arg_tuple = undefined;
290+
291+
// Allow optional Lua state pointer as first parameter. Remaining Lua args will be pushed as is.
292+
const offset = if (arg_fields.len > 0 and arg_fields[0].type == *Lua) blk: {
293+
args[0] = @constCast(&l);
294+
break :blk 1;
295+
} else 0;
296+
297+
// Fill remaining arguments from Lua stack
298+
inline for (arg_fields[offset..], 0..) |field, i| {
299+
args[i + offset] = checkArg(l, @intCast(i + 1), field.type);
290300
}
291301

292302
// Call Zig func and push result
@@ -817,3 +827,23 @@ test "push nested structs and arrays" {
817827
lua.state.pop(1); // Pop config table
818828
try expectEq(lua.state.getTop(), 0);
819829
}
830+
831+
test "function with lua state parameter" {
832+
const lua = try Lua.init(&std.testing.allocator);
833+
defer lua.deinit();
834+
835+
const createTable = struct {
836+
fn f(l: *Lua, name: []const u8) !Lua.Table {
837+
const table = l.createTable(.{});
838+
try table.set("name", name);
839+
return table;
840+
}
841+
}.f;
842+
843+
const globals = lua.globals();
844+
try globals.set("createTable", createTable);
845+
846+
const result = try lua.eval("return createTable('test').name", .{}, Lua.Value);
847+
try expect(std.mem.eql(u8, result.asString().?, "test"));
848+
result.deinit();
849+
}

0 commit comments

Comments
 (0)