Lua中的环境表

概念

lua 将所有的全局变量都存在于一个常规的 table 中,这个 table 称为环境表或简称为环境。(lua 会提供一个全局环境表_G)。默认情况下,每个函数的环境都是_G,因此该函数中的所有全局变量都将从_G中查找。当一个函数被创建时,它将从创建它的函数中继承环境。我们可以使用getfenv(f)来获取当前函数的环境,也可以通过setfevn(f, table)来更改当前函数环境。

getfenv(f)

可以用来获取某一函数的环境,参数f可以是一个函数还可以是一个栈层级。f设为0会得到_G,设为1会得到当前调用getfenv(f)的函数环境,设为2会得到调用当前函数的函数环境,以此类推......

setfenv(f, table)

可以用来为某一函数设置一个新的环境。参数f为0会更改当前运行线程的环境;设为1会更改当前函数的环境;设为2会更改调用当前函数的函数环境,以此类推......

实践

了解基本原理之后,我们就可以利用环境来搞点事情。比如:我们可以 hook lua 中所有全局变量的访问与设置,实现如下。

function change_enviroment()
    local new_env = {} 
    local new_env_meta = {
        __index = function(table, key)
                     --调用change_enviroment的函数中,所有对全局变量的访问操作都会执行到这里
                  end,
        __newindex = function(table, key, value) 
                     --调用change_enviroment的函数中,所有设置全局变量的操作都会执行到这里
                     end
    }
    setmetatable(new_env, new_env_meta) 
    setfenv(2, new_env) --设置调用change_enviroment的函数环境为new_env
end

--设置下环境,此后,所有全局变量的相关操作都会被hook
change_enviroment()

--会执行到__index中
print("xxx") 

--由于是设置一个全局函数,所以会执行到__newindex中
function myFunction()
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

上述例子,我们就可以很轻易地从 lua 通信到原生中,进而可以搞一些事情,比如 hotfix。

最后更新: 11/1/2019, 10:48:00 PM