从lua_pcall(L,0,0,0)获取所有错误

Zep*_*nox 7 c++ lua lua-api

是否有可能从C/C++中获取lua堆栈中的所有错误?这是我尝试过的

C++

int main()
{
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);

    if (luaL_loadfile(L, "LuaBridgeScript.lua"))
    {
        throw std::runtime_error("Unable to find lua file");
    }

    int error = lua_pcall(L, 0, 0, 0);
    while (error && lua_gettop(L))
    {
        std::cout << "stack = " << lua_gettop(L) << "\n";
        std::cout << "error = " << error << "\n";
        std::cout << "message = " << lua_tostring(L, -1) << "\n";
        lua_pop(L, 1);
        error = lua_pcall(L, 0, 0, 0);
    }
}
Run Code Online (Sandbox Code Playgroud)

LUA:

printMessage("hi")
printMessage2("hi2")
Run Code Online (Sandbox Code Playgroud)

输出:

stack = 1
error = 2
message = LuaBridgeScript.lua:1: attempt to call global 'printMessage' <a nil value>
Run Code Online (Sandbox Code Playgroud)

即使堆栈大小为0或负数,我也尝试循环,但我不明白堆栈是如何为负,并且程序在几次尝试后崩溃.

W.B*_*.B. 5

将我的评论总结为答案:

根据Lua docs on lua_pcall, pcall 在成功(块结束)或抛出的第一个错误时返回。所以在后一种情况下,它只会向堆栈推送一条消息。在第一个错误之后它永远不会继续执行。

您想要实现的是检查文件中可能存在的错误。在像 C 这样的静态类型语言中,每个变量都必须在编译时定义,因此编译器可以发现调用不存在的函数的实例。

然而,Lua 是一种动态类型语言,其中变量没有类型,而是值的占位符(确实有类型)。这意味着,Lua 无法提前判断printMessage是函数、字符串、值还是不存在(nil)。只有在运行时,当变量即将被调用时,Lua 才会检查它的类型。

因此,不可能以这种方式实现您想要的。在第一个未处理的错误之后运行代码也是毫无意义的,因为该错误可能会使后续片段中的假设无效(例如关于非现有函数应该设置的全局变量) - 这将是一团糟。

至于语法错误,一般是在编译源文件的时候,也就是加载的时候发现的。但是,Lua 解析器在第一次遇到语法错误时就停止了。这是因为很多时候一个地方的语法错误会使后面的所有内容无效。正如 Etan 在他的评论中指出的那样,许多解析器会报告后续错误,一旦您修复了它们之前的错误,这些错误就会消失或更改。即使是像 MSVS 中的那些重量级解析器,也是如此。