为什么debug.getinfo(1)的'name'是nil?

我正在试图组建一个 Lua 测试框架,可以让你知道有问题的函数,但是当我从 loadstring 切换到 _G 时,(我切换是为了让测试工具能看到函数调用的结果)我的函数开始使用 'nil' 作为函数名。

为什么 _G 不能检测下面代码中的当前函数名呢?另外,当使用 _G 时,我如何获取 loadstring 的返回结果(即 'blah' 调用的 'false')或设置函数名(即告诉 Lua 解释器应该是什么函数名)?

function run_test(one, two)
    if one ~= two then
        print(debug.getinfo(2).name..' Failed')
    end
end

function blah()
    run_test(false, true)
    return false
end

local fname = 'blah'
local status, result = pcall(_G[fname])  -- 输出 'nil';result 是 'false'
local status, result = pcall(loadstring(fname..'()'))  -- 输出 'blah',result 是 'nil'

我主要需要一种使用函数名字符串调用函数的方式,在调用中能够看到函数名(以便测试失败能指向失败的函数,就像上面代码中的 fname = 'blah'),以及能够获取返回值

local fname = 'blah'
status, result = pcall(??某种方式调用 fname??)
assert(status)
assert(not result)

--stdout 应该是 "blah Failed"
点赞
用户107090
用户107090

这是 Lua 所使用的启发式方法提供函数名称的限制。

在 Lua 中,所有函数都是匿名的。一个给定的函数可以是多个变量的值:全局变量、局部变量和表字段。Lua 调试系统尝试根据从字节码中得出的信息确定值的合理名称。

考虑以下简单的例子:

blah()
pcall(blah)

在第一个调用中,调试系统看到被调用的函数来自全局 blah,而且 debug.getinfo(1).name 给出了预期的结果 blah

在第二个调用中,调试系统看到被调用的函数来自 pcall 的第一个参数,但它没有进一步查看那个参数来自哪里,因此 debug.getinfo(1).name 给出了 nil

当你调用 _G[name]() 时,同样的事情也会发生。调试系统只看到一个表的字段,而字段的名称太远了。

尝试将 print(debug.traceback()) 添加为 blah 的第一行,以查看本解释的另一种方式。

2013-08-29 00:15:05