23.1.2 访问Upvalues

我们也可以通过debug库的getupvalue函数访问Lua函数的upvalues。和局部变量不同的是,即使函数不在活动状态他依然有upvalues(这也就是闭包的意义所在)。所以,getupvalue的第一个参数不是栈级别而是一个函数(精确的说应该是一个闭包),第二个参数是upvalue的索引。Lua按照upvalue在一个函数中被引用(refer)的顺序依次编号,因为一个函数不能有两个相同名字的upvalues,所以这个顺序和upvalue并没什么关联(relevant)。

可以使用函数ebug.setupvalue修改upvalues。也许你已经猜到,他有三个参数:一个闭包,一个upvalues索引和一个新的upvalue值。和setlocal类似,这个函数返回upvalue的名字,或者nil(如果upvalue索引超出索引范围)。

下面的代码显示了,在给定变量名的情况下,如何访问一个正在调用的函数的任意的给定变量的值:

function getvarvalue (name)

    local value, found

 

    -- try local variables

    local i = 1

    while true do

       local n, v = debug.getlocal(2, i)

       if not n then break end

       if n == name then

           value = v

           found = true

       end

       i = i + 1

    end

    if found then return value end

 

    -- try upvalues

    local func = debug.getinfo(2).func

    i = 1

    while true do

       local n, v = debug.getupvalue(func, i)

       if not n then break end

       if n == name then return v end

       i = i + 1

    end

 

    -- not found; get global

    return getfenv(func)[name]

end

首先,我们尝试这个变量是否为局部变量:如果对于给定名字的变量有多个变量,我们必须访问具有最高索引的那一个,所以我们总是需要遍历整个循环。如果在局部变量中找不到指定名字的变量,我们尝试这个变量是否为upvalues:首先,我们使用debug.getinfo(2).func获取调用的函数,然后遍历这个函数的upvalues,最后如果我们找到给定名字的变量,我们在全局变量中查找。注意调用debug.getlocaldebug.getinfo的参数2(用来访问正在调用的函数)的用法。


相关链接:
lua程序设计目录 - 中国lua开发者 - lua论坛