例如,我有一张桌子
table.insert( t, 1, function()
print ("rock");
end );
Run Code Online (Sandbox Code Playgroud)
有没有办法从这个表中获取函数名称.我知道我可以像键一样存储名称,但如果我想保留数字索引并且我想知道函数名称怎么办?有什么办法吗?谢谢,提前.
说你有这个代码:
t = {}
x = 5
table.insert(t, 1, x)
Run Code Online (Sandbox Code Playgroud)
t那会是{[1] = 5}."5"只是一个数字 - 它没有名称,并且与变量"x"无关; 这是一个价值.
在Lua中,函数的处理方式与值完全相同:
t = {}
x = function() print("test! :D") end
table.insert(t, 1, x)
Run Code Online (Sandbox Code Playgroud)
x的值不以任何方式,形状或形式与x相关联.如果要手动命名函数,可以通过将函数包装在表中来完成,例如:
t = {}
x = function() print("test! :D") end
table.insert(t, 1, {
name = "MyFunctionName",
func = x
})
Run Code Online (Sandbox Code Playgroud)
你就是这样做的!
...... 除非 ......
你违反了规则!
当Lua开发出来时,开发人员意识到函数的匿名特性会使生产错误消息难以产生,如果不是不可能的话.
你会看到的最好的事情是:
stdin: some error!
stdin: in function 'unknown'
stdin: in function 'unknown'
Run Code Online (Sandbox Code Playgroud)
因此,他们这样做,以便在解析Lua代码时,它会记录一些调试信息,以使生活更轻松.要从Lua本身访问此信息,请提供调试库.
对此库中的函数要非常小心.
使用此库时应小心谨慎.此处提供的功能应专门用于调试和类似任务,例如分析.请抵制将它们用作通常的编程工具的诱惑:它们可能非常慢.此外,这些函数中的一些违反了关于Lua代码的一些假设(例如,函数本地的变量不能从外部访问或者用户数据元表不能通过Lua代码改变),因此可能损害其他安全代码.
要达到理想的效果,必须使用该debug.getinfo功能; 一个例子:
x = function()
print("test!")
print(debug.getinfo(1, "n").name)
end
x() -- prints "test!" followed by "x"
Run Code Online (Sandbox Code Playgroud)
不幸的是,直接在函数上运行的debug.getinfo形式没有填充name参数(debug.getinfo(x, "n").name == nil),上面的版本要求你运行该函数.
这似乎无望!
...... 除非 ......
..你真的违反了规则.
该debug.sethook函数允许您在某些事件中中断运行的Lua代码,甚至在事情发生时更改内容.这与协同程序相结合,可以让你做一些有趣的hacky东西.
这是一个实现debug.getfuncname:
function debug.getfuncname(f)
--[[If name found, returns
name source line
If name not found, returns
nil source line
If error, returns
nil nil error
]]
if type(f) == "function" then
local info = debug.getinfo(f, "S")
if not info or not info.what then
return nil, nil, "Invalid function"
elseif info.what == "C" then
-- cannot be called on C functions, as they would execute!
return nil, nil, "C function"
end
--[[Deep magic, look away!]]
local co = coroutine.create(f)
local name, source, linedefined
debug.sethook(co, function(event, line)
local info = debug.getinfo(2, "Sn")
name = info.namewhat ~= "" and info.name or nil
source, linedefined = info.short_src, info.linedefined
coroutine.yield() -- prevent function from executing code
end, "c")
coroutine.resume(co)
return name, source, linedefined
end
return nil, nil, "Not a function"
end
Run Code Online (Sandbox Code Playgroud)
用法示例:
function test()
print("If this prints, stuff went really wrong!")
end
print("Name = ", debug.getfuncname(test))
Run Code Online (Sandbox Code Playgroud)
这个功能不是很可靠 - 它有时可以工作,而不是其他功能.调试库非常敏感,所以可以预料到.
请注意,您永远不应该将其用于实际的发布代码!仅用于调试!
仍然可以接受的最极端情况是记录已发布软件的错误,以帮助开发人员解决问题.没有重要的代码应该依赖于调试库中的函数.
祝好运!