是否有可能从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);
}
}
LUA:
printMessage("hi")
printMessage2("hi2")
输出:
stack = 1
error = 2
message = LuaBridgeScript.lua:1: attempt to call global 'printMessage' <a nil value>
即使堆栈大小为0或为负,我也尝试循环,但我不明白堆栈是如何为负,并且程序在几次尝试后崩溃。
答案 0 :(得分:4)
将我的评论总结为答案:
根据lua_pcall
上的Lua docs,pcall返回成功(块结束)或第一个错误抛出。所以在后一种情况下,它会将只有一条消息推送到堆栈。在第一次错误之后它永远不会继续执行。
您要实现的目标是检查文件中是否存在错误。在像C这样的静态类型语言中,每个变量都必须在编译时定义,因此编译器可以发现调用非现有函数的实例。
然而,Lua是一种动态类型语言,其中变量没有类型,而是值(具有类型)的占位符。这意味着,Lua无法事先告诉printMessage
是函数,字符串,值还是不存在(nil)。只有在运行时才会调用Lua检查其类型的变量。
因此无法实现您想要的那种方式。运行代码超出第一个未处理的错误也是没有意义的,因为错误可能会使后续片段中的假设无效(例如关于非现有函数应该设置的全局变量) - 这将是一团糟。
对于语法错误,通常在编译源文件时捕获这些错误,即加载时。但是,Lua解析器在第一次遇到语法错误时停止。这是因为在一个地方多次出现语法错误会使其后面的所有内容无效。正如Etan在他的评论中指出的那样,许多解析器报告一旦你修复了它们之前的错误,后续错误就会消失或改变。对于像MSVS那样的重量级解析器也是如此。
答案 1 :(得分:1)
(按照您在评论中澄清的问题)无法报告多个语法错误(仅报告第一个语法错误);所以在下面的片段中只报告了第1行的第一个错误:
if true the --<-- first syntax error
end
if false the --<-- second syntax error
end
然而,您可以编写自己的解析器(或修改现有的Lua解析器之一),即使在找到错误之后也会继续处理。例如,您可以查看David Manura loose parser的工作原理。
无法报告多个运行时错误(仅报告第一个错误);所以在下面的片段中,pcall只报告第一个错误:
pcall(function()
nonExistingFunction1() --<-- only this error will be reported
nonExistingFunction2()
end)