Skip to content

Commit 918e5db

Browse files
luchaknatecraddock
authored andcommitted
Add a method to set the Luau interrupt callback
1 parent 5a7269e commit 918e5db

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

src/lib.zig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ pub const CompareOperator = enum(u2) {
8888
/// Type for C userdata destructors
8989
pub const CUserdataDtorFn = *const fn (userdata: *anyopaque) callconv(.C) void;
9090

91+
/// Type for C interrupt callback
92+
pub const CInterruptCallbackFn = *const fn (state: ?*LuaState, gc: c_int) callconv(.C) void;
93+
9194
/// Type for C useratom callback
9295
pub const CUserAtomCallbackFn = *const fn (str: [*c]const u8, len: usize) callconv(.C) i16;
9396

@@ -2340,6 +2343,12 @@ pub const Lua = opaque {
23402343
return error.Fail;
23412344
}
23422345

2346+
pub fn setInterruptCallbackFn(lua: *Lua, cb: ?CInterruptCallbackFn) void {
2347+
if (c.lua_callbacks(@ptrCast(lua))) |cb_struct| {
2348+
cb_struct.*.interrupt = cb;
2349+
}
2350+
}
2351+
23432352
pub fn setUserAtomCallbackFn(lua: *Lua, cb: CUserAtomCallbackFn) void {
23442353
if (c.lua_callbacks(@ptrCast(lua))) |cb_struct| {
23452354
cb_struct.*.useratom = cb;
@@ -3581,6 +3590,7 @@ pub const ZigHookFn = fn (lua: *Lua, event: Event, info: *DebugInfo) void;
35813590
pub const ZigContFn = fn (lua: *Lua, status: Status, ctx: Context) i32;
35823591
pub const ZigReaderFn = fn (lua: *Lua, data: *anyopaque) ?[]const u8;
35833592
pub const ZigUserdataDtorFn = fn (data: *anyopaque) void;
3593+
pub const ZigInterruptCallbackFn = fn (lua: *Lua, gc: i32) void;
35843594
pub const ZigUserAtomCallbackFn = fn (str: []const u8) i16;
35853595
pub const ZigWarnFn = fn (data: ?*anyopaque, msg: []const u8, to_cont: bool) void;
35863596
pub const ZigWriterFn = fn (lua: *Lua, buf: []const u8, data: *anyopaque) bool;
@@ -3593,6 +3603,7 @@ fn TypeOfWrap(comptime T: type) type {
35933603
ZigContFn => CContFn,
35943604
ZigReaderFn => CReaderFn,
35953605
ZigUserdataDtorFn => CUserdataDtorFn,
3606+
ZigInterruptCallbackFn => CInterruptCallbackFn,
35963607
ZigUserAtomCallbackFn => CUserAtomCallbackFn,
35973608
ZigWarnFn => CWarnFn,
35983609
ZigWriterFn => CWriterFn,
@@ -3611,6 +3622,7 @@ pub fn wrap(comptime value: anytype) TypeOfWrap(@TypeOf(value)) {
36113622
ZigContFn => wrapZigContFn(value),
36123623
ZigReaderFn => wrapZigReaderFn(value),
36133624
ZigUserdataDtorFn => wrapZigUserdataDtorFn(value),
3625+
ZigInterruptCallbackFn => wrapZigInterruptCallbackFn(value),
36143626
ZigUserAtomCallbackFn => wrapZigUserAtomCallbackFn(value),
36153627
ZigWarnFn => wrapZigWarnFn(value),
36163628
ZigWriterFn => wrapZigWriterFn(value),
@@ -3679,6 +3691,15 @@ fn wrapZigUserdataDtorFn(comptime f: ZigUserdataDtorFn) CUserdataDtorFn {
36793691
}.inner;
36803692
}
36813693

3694+
/// Wrap a ZigFn in a CFn for passing to the API
3695+
fn wrapZigInterruptCallbackFn(comptime f: ZigInterruptCallbackFn) CInterruptCallbackFn {
3696+
return struct {
3697+
fn inner(lua: ?*LuaState, gc: c_int) callconv(.C) void {
3698+
@call(.always_inline, f, .{ @as(*Lua, @ptrCast(lua.?)), gc });
3699+
}
3700+
}.inner;
3701+
}
3702+
36823703
/// Wrap a ZigFn in a CFn for passing to the API
36833704
fn wrapZigUserAtomCallbackFn(comptime f: ZigUserAtomCallbackFn) CUserAtomCallbackFn {
36843705
return struct {

src/tests.zig

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2882,3 +2882,38 @@ test "define" {
28822882

28832883
try std.testing.expectEqualSlices(u8, expected, buffer_stream.getWritten());
28842884
}
2885+
2886+
test "interrupt" {
2887+
if (ziglua.lang != .luau) return;
2888+
2889+
var lua = try Lua.init(&testing.allocator);
2890+
defer lua.deinit();
2891+
2892+
const interrupt_handler = struct {
2893+
var times_called: i32 = 0;
2894+
2895+
pub fn inner(l: *Lua, _: i32) void {
2896+
times_called += 1;
2897+
l.setInterruptCallbackFn(null);
2898+
}
2899+
};
2900+
2901+
// Luau only checks for an interrupt callback at certain points, including function calls
2902+
try lua.doString(
2903+
\\function add(a, b)
2904+
\\ return a + b
2905+
\\end
2906+
);
2907+
lua.setInterruptCallbackFn(ziglua.wrap(interrupt_handler.inner));
2908+
2909+
try lua.doString(
2910+
\\c = add(1, 2)
2911+
);
2912+
try testing.expectEqual(1, interrupt_handler.times_called);
2913+
2914+
// Handler should have removed itself
2915+
try lua.doString(
2916+
\\c = add(1, 2)
2917+
);
2918+
try testing.expectEqual(1, interrupt_handler.times_called);
2919+
}

0 commit comments

Comments
 (0)