获取Lua函数的参数名称。
当我调用 Lua 函数时,比如:
PrintMe(MyVariableName)
我希望能够打印出 "MyVariableName",而不是它的值(至少在演示的时候是这样的)。
显然,我可以只传递字符串,但这需要额外的引号,并且我也想打印它的值。
例如,
MyVariable = 4
PrintVariable(MyVariable)
将打印出 "MyVariable is 4" 或者其他什么。
我不想重复变量的名称和值,比如
PrintVariable(MyVariable, "MyVariable")
因为这是不必要的重复。
Lua 能否处理这个问题呢?
我现在的做法是将变量名放在引号中传递,并使用 loadstring 来获取值,但我希望能够直接传递变量,而不需要额外的引号(我原以为 debug.getlocal 可以做到这一点,但它返回的是值而不是名称)。
下面是一个模拟示例:
function printme1(var, val)
print(var.." = "..val)
end
function printme2(v)
local r
loadstring("r = "..v)() -- equivalent to r = a but must be used since v is a string representing a and not the object a
print(v.." = "..tostring(r))
end
function printme3(v)
-- unknown
end
a = 3
printme1("a", a)
printme2("a")
printme3(a)
在这种情况下,所有 3 个函数都应该打印相同的结果。printme3 显然是最方便的。
原文链接 https://stackoverflow.com/questions/10458306
你可以使用 debug 库来实现类似这样的事情... 下面的代码可以达到你想要的效果:
``` function a_func(arg1, asdf) -- 如果这个函数没有使用参数... 在调用 debug.getlocal() 的时候会显示 (*temporary),因为它们没有被使用... if arg1 == "10" then end if asdf == 99 then end -- 处理 arg1 和 asdf? end
-- 一个将变量以易读的格式输出的函数 function myUnpack(tbl) if type(tbl) ~= "table" then return "" end
local ret = ""
for k,v in pairs(tbl) do
if tostring(v) ~= "" then
ret = ret.. tostring(k).. "=".. tostring(v).. ", "
end
end
return string.gsub(ret, ", $", "")
end
function hook() -- 把 2 传给 debug.getinfo 函数意味着“告诉我在调用这个函数时引发了这个调用的函数的信息”。1 级是调用 hook 的 C 函数。 local info = debug.getinfo(2) if info ~= nil and info.what == "Lua" then local i, variables = 1, {""} -- 现在遍历 Lua 栈中该层的所有局部变量 while true do local name, value = debug.getlocal(2, i) if name == nil then break end -- 这只是跳过未使用的变量 if name ~= "(*temporary)" then variables[tostring(name)] = value end i = i + 1 end -- 这是一个输出被调用的函数信息的函数 print((info.name or "unknown").. "(".. myUnpack(variables).. ")") end end
--
你不能说PrintVariable(MyVariable)
,因为 Lua 没有办法确定哪个变量(如果有的话;可能使用了常量)被用作传递给函数的参数。但是,你可以说 PrintVariable('MyVariable')
,然后使用 debug API 在调用者的作用域中查找具有该名称的本地变量:
function PrintVariable(name)
--默认显示具有该名称的全局变量(如果有的话)
local value = _G[name]
--查找调用者作用域中是否有具有该名称的本地变量
for i=1,math.huge do
local localname, localvalue = debug.getlocal(2,i,1)
if not localname then
break --没有更多的本地变量需要检查
elseif localname == name then
value = localvalue
end
end
if value then
print(string.format("%s = %s", name, tostring(value)))
else
print(string.format("没有找到名为 '%s' 的变量。", name))
end
end
现在,你可以这样说:
PrintVariable('MyVariable')
这种情况下将打印 "MyVariable = 4"。
不过,如果你真的想在不使用引号的情况下做到这一点,你可以检查调用者的本地变量,以找到一个具有指定值的变量名称,但是,如果在调用者的作用域中存在一个以上具有相同值的变量,那么有时会打印错误的变量名称。话虽如此,这里是如何做到这一点的:
function PrintVariable(value)
local name
--查找调用者的作用域中是否有具有指定值的本地变量
for i=1,math.huge do
local localname, localvalue = debug.getlocal(2,i,1)
if not localname then
break
elseif localvalue == value then
name = localname
end
end
--如果找不到变量,则检查全局变量
if not name then
for globalname, globalvalue in pairs(_G) do
if globalvalue == value then
name = globalname
end
end
end
if name then
print(string.format("%s = %s", name, tostring(value)))
else
print(string.format("没有找到值为 '%s' 的变量。", tostring(value)))
end
end
现在,你可以说PrintVariable(MyVariable)
,但是,如果在调用者作用域中存在一个具有值 4
的变量,并且出现在 MyVariable
之前,那么将打印 那个 变量的名称。
你可以使用以下这个形式:
local parms = { "MyVariable" }
local function PrintVariable(vars)
print(parms[1]..": "..vars[1])
end
local MyVariable = "bar"
PrintVariable{MyVariable}
输出结果为:
MyVariable: bar
虽然这种方法不够通用,但确实很简单。通过这种方式,您可以避免使用 debug 库和 loadstring 函数。如果您的编辑器好的话,可以编写宏来执行此操作。
另一种可能的解决方案是自己添加此功能。Lua C API和源码都非常简单且可扩展。
我们不知道你的项目/工作的上下文,但是如果你正在制作/嵌入自己的Lua构建,则可以通过在debug
库中添加相应功能来扩展它。
Lua通过引用传递它的值,但是我们不清楚这些值中是否包含字符串名称,如果包含的话是否容易访问。
在你的示例中,该值声明与以下行相同:
_G["MyVariable"] = 4
因为它是全局的。如果它被声明为local
,那么就像其他人在这里所说的那样,你可以通过debug.getlocal()
枚举它们。但是,在实际引用上下文的C上下文中可能并不重要。
实现一个debug.getargumentinfo(...)
,将名称键值对扩展到参数表中。
这是一个相当古老的话题,我很抱歉让它死灰复燃。
根据我的Lua经验,最接近OP所要求的东西就是这样的:
PrintVariable = {}
setmetatable(PrintVariable, {__index = function (self, k, v) return string.format('%s = %s', k, _G[k]) end})
VAR = 0
VAR2 = "Hello World"
print(PrintVariable.VAR, PrintVariable.VAR2)
-- Result: VAR = 0 VAR2 = Hello World
我不会赘述太多解释,因为代码相当易读,然而:
这里发生的事情很简单,你只需给PrintVariable
变量设置一个元表,然后添加__index
元方法,当表强制在其索引中搜索值时被调用,借助这种功能,你可以实现在示例中看到的效果。
参考:https://www.lua.org/manual/5.1/manual.html
我希望未来和新访客会发现这很有帮助。
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
我有一个坏消息,朋友。你可以按照它们出现在函数顶部的方式访问函数参数名称,但是访问它们在调用函数中确切命名的数据不存在。看以下示例:
function PrintVariable(VariableToPrint) --我们可以使用debug.getinfo()来确定名称为'VariableToPrint'的变量 --我们无法确定名称为'MyVariable'的变量,除非使用一些非常复杂的方法(参见VBRonPaulFan在他自己的答案中的评论) print(VariableToPrint); end MyVariable = 4 PrintVariable(MyVariable)
为说明这一点,想象一下如果我们这样做:
x = 4 MyVariable = x MyOtherVariable = x x = nil PrintVariable(MyVariable)
现在,如果你是Lua,你会将哪个名称附加到传递给函数的变量的元数据中?是的,你可以使用debug.getint()向上遍历堆栈查找传入的变量,但你可能会发现几个引用。 还要考虑:
PrintVariable("StringLiteral")
你会如何称呼这个变量?它有一个值,但没有名称。