Print stacktrace from C code with embedded lua

后端 未结 4 1945
温柔的废话
温柔的废话 2020-12-31 01:54

If I understand this correctly, Lua by default will call the debug library \"debug.traceback\" when an error occurs.

However, when embedding Lua into C code like don

相关标签:
4条回答
  • 2020-12-31 02:35

    Lua by default will call the debug library "debug.traceback" when an error occurs.

    No, it won't. The Lua runtime (lua.exe) will do that, but the Lua library will not do that on its own. If you want a call-stack with your Lua errors, then you need to generate one.

    The Lua runtime does this by using lua_pcall's error function. The stack has not been unwound when the error function is called, so you can get a stack trace there. The error function the runtime uses is this one:

    static int traceback (lua_State *L) {
      if (!lua_isstring(L, 1))  /* 'message' not a string? */
        return 1;  /* keep it intact */
      lua_getfield(L, LUA_GLOBALSINDEX, "debug");
      if (!lua_istable(L, -1)) {
        lua_pop(L, 1);
        return 1;
      }
      lua_getfield(L, -1, "traceback");
      if (!lua_isfunction(L, -1)) {
        lua_pop(L, 2);
        return 1;
      }
      lua_pushvalue(L, 1);  /* pass error message */
      lua_pushinteger(L, 2);  /* skip this function and traceback */
      lua_call(L, 2, 1);  /* call debug.traceback */
      return 1;
    }
    
    0 讨论(0)
  • 2020-12-31 02:39

    mxcl's code has some problem:

    static int traceback(lua_State *L) {
        lua_getfield(L, LUA_GLOBALSINDEX, "debug");
        lua_getfield(L, -1, "traceback");
        //---------------------------
        lua_pop(L,-2); //to popup the 'debug'
        //---------------------------
        lua_pushvalue(L, 1);
        lua_pushinteger(L, 2);
        lua_call(L, 2, 1);
        fprintf(stderr, "%s\n", lua_tostring(L, -1));
        return 1;
    }
    
    0 讨论(0)
  • 2020-12-31 02:52

    Working off Nicol’s answer above here is a working example:

    static int traceback(lua_State *L) {
        lua_getfield(L, LUA_GLOBALSINDEX, "debug");
        lua_getfield(L, -1, "traceback");
        lua_pushvalue(L, 1);
        lua_pushinteger(L, 2);
        lua_call(L, 2, 1);
        fprintf(stderr, "%s\n", lua_tostring(L, -1));
        return 1;
    }
    
    int main(int argc, char **argv) {
        lua_State *L = lua_open();
        luaL_openlibs(L);    
        lua_pushcfunction(L, traceback);
        int rv = luaL_loadfile(L, "src/main.lua");
        if (rv) {
            fprintf(stderr, "%s\n", lua_tostring(L, -1));
            return rv;
        } else {
            return lua_pcall(L, 0, 0, lua_gettop(L) - 1);
        }
    }
    
    0 讨论(0)
  • 2020-12-31 02:55

    I met the some question as you do,and I found this way work:

    luaL_traceback(L, L, NULL, 1);
    printf("%s\n", lua_tostring(L, -1));
    

    SinceluaL_tracebackis exactlydebug.traceback() using to print the stack,so I think this may be a proper way,and you can read the API manual aboutluaL_traceback or just read the source code of Lua to figure out the what the params means.

    0 讨论(0)
提交回复
热议问题