默认的lua_pcall错误处理程序(从Lua 5.3开始)不执行任何操作,使异常消息保留在堆栈的顶部。我们想要更改此设置,以便在luaL_traceback失败时,除了堆栈顶部的异常消息之外,还获得lua_pcall追溯。

不幸的是,我认为这意味着我们需要在所有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函数中,但是我有两个问题:
  • 在调用之前(或内部)是否可以通过更复杂的堆栈操作来打破这种方法? (我还不太熟悉Lua堆栈)
  • ,因为我们希望对大多数pcall进行追溯,因此有必要将此错误处理程序设为默认值,并手动指定先前的错误处理程序(不执行任何操作),因此有一种方法可以全局更改默认值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;
    }
    

    10-07 16:32
    查看更多