Lua 设置默认错误处理器。

默认的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中引入噪声(因为我们有很多,因为我们有一些从C异步调用的Lua回调),并且感觉有点重复。我认为这可以包装在某些lua_mypcall函数内,自动执行这些设置工作,但是我有两个问题:

1.在pcall之前(或内部)进行了更复杂的堆栈操作,这种方法是否容易出错? (我对Lua堆栈还不是很熟悉)

2.由于我们希望在大多数pcall上获得回溯,因此将该错误处理程序设置为默认值并手动指定先前没有任何操作的先前错误处理程序是有意义的,因此是否有一种方法可以全局更改Lua状态的默认错误处理程序?

我看到lua_pcallk中有一些代码用于errfunc == 0,但它似乎不能配置。我们可以修改Lua实现以手动更改默认设置,但是希望避免这样做。

我们正在使用Lua 5.3。谢谢。

点赞
用户3677376
用户3677376

你的基本方法是对的,但是你缺少了一个 lua_remove (而不是 lua_pop),并且你的栈索引是错误的。尝试这个:

int lua_mypcall( lua_State* L, int nargs, int nret ) {
  /* 计算消息处理程序的堆栈位置 */
  int hpos = lua_gettop( L ) - nargs;
  int ret = 0;
  /* 推送自定义错误消息处理程序 */
  lua_pushcfunction( L, my_error_handler );
  /* 将其放在函数和参数之前 */
  lua_insert( L, hpos );
  /* 调用带有自定义处理程序的 lua_pcall 函数 */
  ret = lua_pcall( L, nargs, nret, hpos );
  /* 从堆栈中删除自定义错误消息处理程序 */
  lua_remove( L, hpos );
  /* 传递 lua_pcall 的返回值 */
  return ret;
}
2015-05-04 03:34:06
用户2170324
用户2170324
如果(lua_pcall(L,0,0,0)!=LUA_OK) fprintf(stderr,"%s\n", lua_tostring(L,-1) );

约等于:

如果调用函数 lua_pcall(L,0,0,0) 返回值不等于 LUA_OK,那么输出错误信息到 stderr,错误信息为栈顶元素(在 Lua 栈中的索引为 -1)的字符串表达式。
2022-04-19 17:54:25