Lua 设置默认错误处理程序
Lua set default error handler
默认的 lua_pcall
错误处理程序(自 Lua 5.3 起)不执行任何操作,让异常消息保留在堆栈顶部。我们想更改此设置,以便在 lua_pcall
失败时,除了堆栈顶部的异常消息之外,我们还可以获得 luaL_traceback
回溯。
不幸的是,我认为这意味着我们需要在所有 pcall 的正下方插入错误处理程序。最稳健的做法似乎是这样的:
/* push function and arguments */
lua_pushstuff...
/* push error handler */
lua_pushcfunction(L, my_error_handler);
/* move the error handler just below the function and arguments */
lua_insert(L, -(number of args + 1));
if (lua_pcall(L, nargs, nresults, -(number of args + 1))) {
/* error here (my_error_handler was invoked) */
/* do something with lua_tostring(L, -1) */
}
/* afterwards, pop the error handler (it may be below return values) */
lua_pop(L, 1);
但这会在每个 pcall 中引入噪音(我们有很多,因为我们有一些 Lua 从 C 异步调用的回调)并且感觉有点重复。我认为这可以包含在某些 lua_mypcall
自动执行此设置的函数中,但我有两个问题:
这种方法是否容易因 pcall 之前(或内部)更复杂的堆栈操作而中断? (我还不是很精通 Lua 堆栈)
由于我们希望对大多数 pcalls 进行回溯,因此将此错误处理程序设为默认值并手动指定先前的错误处理程序(不执行任何操作)是有意义的,因此有没有办法全局更改 Lua 状态的默认错误处理程序?
我看到 lua_pcallk
有一些 errfunc == 0
的代码,但它似乎不可配置。我们可以破解 Lua 实现以手动更改默认值,但希望避免这种情况。
我们正在使用 Lua 5.3。谢谢。
您的基本方法是合理的,但是您缺少 lua_remove
(而不是 lua_pop
)并且您的堆栈索引是错误的。试试这个:
int lua_mypcall( lua_State* L, int nargs, int nret ) {
/* calculate stack position for message handler */
int hpos = lua_gettop( L ) - nargs;
int ret = 0;
/* push custom error message handler */
lua_pushcfunction( L, my_error_handler );
/* move it before function and arguments */
lua_insert( L, hpos );
/* call lua_pcall function with custom handler */
ret = lua_pcall( L, nargs, nret, hpos );
/* remove custom error message handler from stack */
lua_remove( L, hpos );
/* pass return value of lua_pcall */
return ret;
}
if (lua_pcall(L,0,0,0)!=LUA_OK) fprintf(stderr,"%s\n", lua_tostring(L,-1) );
默认的 lua_pcall
错误处理程序(自 Lua 5.3 起)不执行任何操作,让异常消息保留在堆栈顶部。我们想更改此设置,以便在 lua_pcall
失败时,除了堆栈顶部的异常消息之外,我们还可以获得 luaL_traceback
回溯。
不幸的是,我认为这意味着我们需要在所有 pcall 的正下方插入错误处理程序。最稳健的做法似乎是这样的:
/* push function and arguments */
lua_pushstuff...
/* push error handler */
lua_pushcfunction(L, my_error_handler);
/* move the error handler just below the function and arguments */
lua_insert(L, -(number of args + 1));
if (lua_pcall(L, nargs, nresults, -(number of args + 1))) {
/* error here (my_error_handler was invoked) */
/* do something with lua_tostring(L, -1) */
}
/* afterwards, pop the error handler (it may be below return values) */
lua_pop(L, 1);
但这会在每个 pcall 中引入噪音(我们有很多,因为我们有一些 Lua 从 C 异步调用的回调)并且感觉有点重复。我认为这可以包含在某些 lua_mypcall
自动执行此设置的函数中,但我有两个问题:
这种方法是否容易因 pcall 之前(或内部)更复杂的堆栈操作而中断? (我还不是很精通 Lua 堆栈)
由于我们希望对大多数 pcalls 进行回溯,因此将此错误处理程序设为默认值并手动指定先前的错误处理程序(不执行任何操作)是有意义的,因此有没有办法全局更改 Lua 状态的默认错误处理程序?
我看到 lua_pcallk
有一些 errfunc == 0
的代码,但它似乎不可配置。我们可以破解 Lua 实现以手动更改默认值,但希望避免这种情况。
我们正在使用 Lua 5.3。谢谢。
您的基本方法是合理的,但是您缺少 lua_remove
(而不是 lua_pop
)并且您的堆栈索引是错误的。试试这个:
int lua_mypcall( lua_State* L, int nargs, int nret ) {
/* calculate stack position for message handler */
int hpos = lua_gettop( L ) - nargs;
int ret = 0;
/* push custom error message handler */
lua_pushcfunction( L, my_error_handler );
/* move it before function and arguments */
lua_insert( L, hpos );
/* call lua_pcall function with custom handler */
ret = lua_pcall( L, nargs, nret, hpos );
/* remove custom error message handler from stack */
lua_remove( L, hpos );
/* pass return value of lua_pcall */
return ret;
}
if (lua_pcall(L,0,0,0)!=LUA_OK) fprintf(stderr,"%s\n", lua_tostring(L,-1) );