@@ -277,16 +277,26 @@ pub fn pushResult(lua: Lua, result: anytype) c_int {
277277/// Creates a Lua C function from a Zig function.
278278fn 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