4

我正在尝试组合一个 lua 测试框架,让您知道有问题的函数,但是当我从 loadstring 切换到 时_G,(我切换以便我的测试工具可以看到函数调用的结果)我的函数开始使用'nil' 代表函数名

为什么_G在下面的代码中检测不到当前函数的名称?另外,如何从 loadstring 获取返回结果(即来自 blah 调用的“false”)或在使用时设置函数名称_G(即告诉 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])  -- Outputs 'nil'; result is 'false'
local status, result = pcall(loadstring(fname..'()'))  -- Outputs 'blah', result is 'nil'

我需要的主要是一种使用函数名称字符串调用函数的方法,能够在调用中看到函数名称(测试失败指向失败的函数,如 fname = 'blah' 在上面的代码)并能够得到返回值

local fname = 'blah'
status, result = pcall(??Call fname somehow??)
assert(status)
assert(not result)

--stdout should be "blah Failed"
4

1 回答 1

3

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

在 Lua 中,所有函数都是匿名的。给定函数可以是多个变量的值:全局、本地和表字段。Lua 调试系统通过查看正在执行的字节码,尝试根据值的来源找到合理的名称。

考虑更简单的例子

blah()
pcall(blah)

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

在第二次调用中,调试系统看到被调用的函数来自第一个参数,pcall但它没有进一步查看该参数的来源,并debug.getinfo(1).name给出nil.

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

尝试添加print(debug.traceback())作为第一行blah以查看对此解释的另一种看法。

于 2013-08-29T00:15:05.607 回答