获取lua中函数的参数名称

获取lua中函数的参数名称,lua,Lua,当调用lua函数时,如 PrintMe(MyVariableName) 我希望能够真正打印“MyVariableName”,而不是它的值(为了演示目的) 显然,我可以传递字符串,但这需要额外的引号,我还想打印它的值 e、 g MyVariable = 4 PrintVariable(MyVariable) 会打印“MyVariable是4”或其他内容吗 我不想像这样重复名称和变量 PrintVariable(MyVariable, "MyVariable") 因为这是不必要的重复 卢阿能应付

当调用lua函数时,如

PrintMe(MyVariableName)

我希望能够真正打印“MyVariableName”,而不是它的值(为了演示目的)

显然,我可以传递字符串,但这需要额外的引号,我还想打印它的值

e、 g

MyVariable = 4
PrintVariable(MyVariable)
会打印“MyVariable是4”或其他内容吗

我不想像这样重复名称和变量

PrintVariable(MyVariable, "MyVariable")
因为这是不必要的重复

卢阿能应付吗

我现在要做的是在引号中传递变量名,并使用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显然是最方便的。

我有个坏消息,我的朋友。您可以访问显示在函数顶部的函数参数名称,但要访问调用函数中的名称所需的数据不存在。见下文:

function PrintVariable(VariableToPrint)
  --we can use debug.getinfo() to determine the name 'VariableToPrint'
  --we cannot determine the name 'MyVariable' without some really convoluted stuff (see comment by VBRonPaulFan on his own answer)
  print(VariableToPrint);
end

MyVariable = 4
PrintVariable(MyVariable)
为了说明这一点,想象一下如果我们做了:

x = 4
MyVariable = x
MyOtherVariable = x
x = nil

PrintVariable(MyVariable)
现在,如果您是Lua,您会在元数据中将什么名称附加到最终传递给函数的变量?是的,您可以使用debug.getint()在堆栈中查找传入的变量,但是您可能会找到多个引用。 还应考虑:

PrintVariable("StringLiteral")

那个变量叫什么?它有一个值,但没有名称。

您可以使用调试库执行类似的操作。。。像这样的东西确实是你想要的:

function a_func(arg1, asdf)
    -- if this function doesn't use an argument... it shows up as (*temporary) in 
    -- calls to debug.getlocal() because they aren't used...
    if arg1 == "10" then end
    if asdf == 99 then end
    -- does stuff with arg1 and asdf?
end

-- just a function to dump variables in a user-readable format
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()
    -- passing 2 to to debug.getinfo means 'give me info on the function that spawned 
    -- this call to this function'. level 1 is the C function that called the hook.
    local info = debug.getinfo(2)
    if info ~= nil and info.what == "Lua" then
        local i, variables = 1, {""}
        -- now run through all the local variables at this level of the lua stack
        while true do
            local name, value = debug.getlocal(2, i)
            if name == nil then
                break
            end
            -- this just skips unused variables
            if name ~= "(*temporary)" then
                variables[tostring(name)] = value
            end
            i = i + 1
        end
            -- this is what dumps info about a function thats been called
        print((info.name or "unknown").. "(".. myUnpack(variables).. ")")
    end
end

-- tell the debug library to call lua function 'hook 'every time a function call
-- is made...
debug.sethook(hook, "c")

-- call a function to try it out...
a_func("some string", 2012)
这将导致输出:

a_func(asdf=2012, arg1=some string)

你可以做一些更有趣的事情来修饰它,但这基本上涵盖了如何做你要做的事情。

你不能说
PrintVariable(MyVariable)
,因为Lua无法确定哪个变量(如果有的话;可以使用常量)被用来向函数传递参数。但是,您可以说
PrintVariable('MyVariable')
,然后使用调试API在调用者的作用域中查找具有该名称的局部变量:

function PrintVariable(name)
  -- default to showing the global with that name, if any
  local value = _G[name]

  -- see if we can find a local in the caller's scope with that name
  for i=1,math.huge do
    local localname, localvalue = debug.getlocal(2,i,1)
    if not localname then
      break -- no more locals to check
    elseif localname == name then
      value = localvalue
    end
  end

  if value then
    print(string.format("%s = %s", name, tostring(value)))
  else
    print(string.format("No variable named '%s' found.", name))
  end
end
现在你可以说:

PrintVariable('MyVariable')
而在本例中,将打印“MyVariable=4”


不是,如果您真的想在没有引号的情况下执行此操作,您可以检查调用者的局部变量是否具有提供的值,但是如果调用者的作用域中有多个具有给定值的变量,则偶尔会给您错误的变量名。话虽如此,以下是您的做法:

function PrintVariable(value)
  local name

  -- see if we can find a local in the caller's scope with the given value
  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 we couldn't find a local, check globals
  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("No variable found for the value '%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

它不是通用的,但很简单。这样做可以避免调试库和loadstring。如果你的编辑器很好,你可以编写一个宏来完成它。

另一个可能的解决方案是自己添加这个工具。 luaapi和源代码非常简单且可扩展

我/我们不知道您的项目/工作的上下文,但是如果您正在制作/嵌入自己的Lua构建,您可以使用一些东西来扩展
debug

Lua通过引用传递它的值,但如果这些值中包含字符串名称,并且如果可以轻松访问,则立即未知

在您的示例中,值声明与以下内容相同:

_G["MyVariable"] = 4
因为它是全球性的。如果声明为
local
,则与此处所述的其他声明一样,您可以通过
debug.getlocal()
枚举这些声明。但是,在实际引用上下文的C上下文中,这可能并不重要


实现一个
debug.getargumentinfo(…)
,它使用名称键、值对扩展参数表。

这是一个非常古老的主题,很抱歉让它复活了

根据我对lua的经验,我所知道的最接近OP要求的是:

PrintVariable={}
setmetatable(PrintVariable,{{uuuu index=function(self,k,v)返回字符串。格式('%s=%s',k,u G[k])end})
VAR=0
VAR2=“你好,世界”
打印(PrintVariable.VAR,PrintVariable.VAR2)
--结果:VAR=0 VAR2=Hello World
我不会给出更多解释,因为代码可读性很强,但是: 这里发生的事情很简单,您只需将一个元表设置为
PrintVariable
变量,并添加
\uu index
元方法,当强制表在其索引中搜索值时,会调用该元方法,由于此功能,您可以实现示例中所示的效果

参考:


我希望未来的和新的访问者会觉得这很有帮助。

你误读了原文。他希望确定函数范围外变量的名称(请参见他当前的解决方案),而不是函数用于参数的名称。换句话说,如果调用方执行了a_func(a,b),他不是要确定“asdf”和“arg1”,而是要确定“a”和“b”。啊,明白了。如果您尝试遍历堆栈,试图找出哪些局部变量在作用域中,并且与传递给被调用函数的值相匹配,那么这可能是可能的。对于一个演示来说,似乎有很多工作要做,但是…OP无法恢复他想要的变量名,但是“局部变量名不再存在”这一说法是不正确的。您可以使用
debug.getlocal
将它们全部恢复。但是,它们会根据堆栈级别和创建顺序进行恢复。无法恢复用于将值传递给函数的值。我不确定你是否理解我想要的内容Nathan(或者我不理解你)。。。我已经更新了我的帖子,加入了我使用的代码,但是使用cavet我必须传递字符串。对不起,我编辑了我的帖子,试图对自己做更多的解释