@@ -98,6 +98,18 @@ pub const Lua = opaque {
9898 return if (lua ) | p | p else error .OutOfMemory ;
9999 }
100100
101+ /// Sets a new panic function and returns the old one. If an error happens outside any protected environment,
102+ /// Lua calls a panic function and then calls exit(EXIT_FAILURE), thus exiting the host application.
103+ /// Your panic function can avoid this exit by never returning (e.g., doing a long jump).
104+ /// The panic function can access the error message at the top of the stack.
105+ ///
106+ /// From: `lua_CFunction lua_atpanic(lua_State *L, lua_CFunction panicf);`
107+ /// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_atpanic
108+ /// Stack Behavior: `[-0, +0, -]`
109+ pub fn atPanic (lua : * Lua , f : ? CFunction ) ? CFunction {
110+ return @ptrCast (c .lua_atpanic (asState (lua ), @ptrCast (f )));
111+ }
112+
101113 /// Returns the memory-allocation function and user data configured in the given lua instance.
102114 /// If userdata is not null, Lua internally saves the user data pointer passed to `lua_newstate`.
103115 ///
@@ -1120,8 +1132,8 @@ pub const Lua = opaque {
11201132 /// From: `int lua_cpcall(lua_State *L, lua_CFunction func, void *ud);`
11211133 /// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_cpcall
11221134 /// Stack Behavior: `[-0, +(0|1), -]`
1123- pub fn protectedCallCFunction (lua : * Lua , func : CFunction , ud : ? * anyopaque ) ProtectedCallError ! void {
1124- const res = c .lua_cpcall (asState (lua ), @ptrCast (func ), ud );
1135+ pub fn protectedCallCFunction (lua : * Lua , f : CFunction , ud : ? * anyopaque ) ProtectedCallError ! void {
1136+ const res = c .lua_cpcall (asState (lua ), @ptrCast (f ), ud );
11251137 assert (Status .is_status (res )); // Expected the status to be one of the "thread status" values defined in lua.h
11261138
11271139 return parseCallStatus (res );
@@ -2062,3 +2074,22 @@ test "proctected call for c functions" {
20622074 try std .testing .expectError (Lua .CallError .Runtime , actual );
20632075 try std .testing .expectEqualSlices (u8 , "EXPECTED ERROR 123" , try lua .toLString (-1 ));
20642076}
2077+
2078+ fn newPanicFunction (lua : * Lua ) callconv (.c ) i32 {
2079+ _ = lua ;
2080+ return 0 ;
2081+ }
2082+
2083+ test "override error function with atpanic" {
2084+ const lua = try Lua .init (std .testing .allocator );
2085+ defer lua .deinit ();
2086+
2087+ // This test case is actually kind of useless, I don't want to hack doing a long jump into these tests
2088+ // to avoid application exit. So we will just call the function and make sure the application doesn't
2089+ // crash. But it's not really testing that the panic function gets called in any way right now.
2090+
2091+ const actual = lua .atPanic (newPanicFunction );
2092+ try std .testing .expect (actual == null );
2093+ const new = lua .atPanic (actual );
2094+ try std .testing .expect (new .? == newPanicFunction );
2095+ }
0 commit comments