Lua全局对象 _G详细介绍及应用分享
lua里面的_G全局对象 其实就是一个table 里面存储了lua运行所需要的所有函数和table
类似于js里面的 window对局对象,在lua里面定义的全局变量都会储存到_G的table下,但是要注意以local申明的变量是局部的变量 不会挂载到_G的table下
LuatOS测试
我们可以写一个简单的循环来打印_G下所有的变量,你可以在LuatOS内进行代码的在线测试
function aaaaaaaaaaaaaaaaaaaaaaaaaaa()
print("测试函数")
end
for k,v in pairs(_G) do
print(k.." ("..type(v)..")")
end
执行上面代码在LuatOS在线测试网页中执行 输出如下内容
-- [08:26:12] 虚拟机初始化完毕 -- [08:26:12] assert (function) -- [08:26:12] collectgarbage (function) -- [08:26:12] dofile (function) -- [08:26:12] error (function) -- [08:26:12] getmetatable (function) -- [08:26:12] ipairs (function) -- [08:26:12] load (function) -- [08:26:12] loadfile (function) -- [08:26:12] next (function) -- [08:26:12] pairs (function) -- [08:26:12] pcall (function) -- [08:26:12] print (function) -- [08:26:12] rawequal (function) -- [08:26:12] rawget (function) -- [08:26:12] rawlen (function) -- [08:26:12] rawset (function) -- [08:26:12] select (function) -- [08:26:12] setmetatable (function) -- [08:26:12] tonumber (function) -- [08:26:12] tostring (function) -- [08:26:12] type (function) -- [08:26:12] xpcall (function) -- [08:26:12] _G (table) -- [08:26:12] _VERSION (string) -- [08:26:12] require (function) -- [08:26:12] package (table) -- [08:26:12] coroutine (table) -- [08:26:12] table (table) -- [08:26:12] os (table) -- [08:26:12] string (table) -- [08:26:12] math (table) -- [08:26:12] utf8 (table) -- [08:26:12] debug (table) -- [08:26:12] fengari (table) -- [08:26:12] js (table) -- [08:26:12] sysLuaStartTimer (function) -- [08:26:12] sysLuaStopTimer (function) -- [08:26:12] utils (boolean) -- [08:26:12] json (table) -- [08:26:12] loadstring (function) -- [08:26:12] pack (table) -- [08:26:12] unpack (function) -- [08:26:12] BIT (table) -- [08:26:12] bit (table) -- [08:26:12] @jsTriggerList (table) -- [08:26:12] jsTriggerRegister (function) -- [08:26:12] log (table) -- [08:26:12] gpio (table) -- [08:26:12] adc (table) -- [08:26:12] pwm (table) -- [08:26:12] JS_FUNCTION_SYS_RUN (function) -- [08:26:12] aaaaaaaaaaaaaaaaaaaaaaaaaaa (function) -- [08:26:12] 虚拟机已停止运行
Androlua测试
由于在控制台可能不方便看到table内部的元素,所以我在androlua中写了一个简单的对话框来展示_G全局对象下的所有元素,支持返回,代码如下
--debug.getinfo 返回对象可选属性
-- source: 函数定义所在的源代码文件名。如果函数定义不在当前文件中,则返回空字符串。
-- name: 函数名。
-- currentline: 函数定义所在的行号。如果函数定义不在当前文件中,则返回 -1。
-- nups: 函数的参数个数。
-- what: 函数的类型("main"、"C"、"Lua"、"tail")。
-- short_src: 函数定义所在的源代码文件名的缩写形式。如果函数定义不在当前文件中,则返回空字符串。
-- linedefined: 函数定义所在的行号。如果函数定义不在当前文件中,则返回 -1。
-- lastlinedefined: 函数上一次被修改的代码所在的行号。如果函数没有修改过,则返回 -1。
-- maxstacksize: 函数调用栈的最大深度。
-- upvaluecount: 函数闭包中 upvalue 的数量。
function aaaaaaaaaaaaaaaaaaaaaaaaa()
print("测试函数")
end
local G_Data = {} --用于全局返回
local keys = {}
local values = {}
for k,v in pairs(_G) do
if type(v) ~= "function" then
table.insert(keys,k.." ("..type(v)..")")
table.insert(values,v)
end
end
-- 显示对话框的函数
function showDialog(isList,title,massge,keysData,valuesData)
dialog=AlertDialog.Builder(this)
dialog.setTitle(title)
if isList then
dialog.setItems(keysData,{onClick=function(l,v)
if table.concat({"table","userdata"},","):find(type(valuesData[v+1]))then
local tempKeys = {}
local tempValues = {}
if type(valuesData[v+1])~="userdata" then
ergodic= valuesData[v+1]
else
ergodic= getmetatable(valuesData[v+1])
end
for m,n in pairs(ergodic) do
table.insert(tempKeys,m.." ("..type(n)..")")
table.insert(tempValues,n)
end
G_Return={keys=tempKeys,values=tempValues,title=keysData[v+1]}
table.insert(G_Data,G_Return)
showDialog(true,keysData[v+1],nil,tempKeys,tempValues)--使用例子
end
if type(valuesData[v+1]) =="function" then
local funcInfo = debug.getinfo(valuesData[v+1])
-- print(debug.dump(funcInfo.func))
print(funcInfo.source)
-- local funcInfo2 = debug.getinfo(funcInfo.func)
--print(funcInfo2)
-- for kl,mq in pairs(funcInfo) do
-- if kl~="source" then
-- print(kl,mq)
-- else
-- print(kl,mq)
-- end
-- end
-- local funcString = string.format("%s:%d", funcInfo.source, funcInfo.currentline)
-- print(123,funcString)
end
print(type(valuesData[v+1]))
if table.concat({"string","number"},","):find(type(valuesData[v+1])) then
G_Return={keys="",values=""}
table.insert(G_Data,G_Return)
showDialog(false,keysData[v+1],valuesData[v+1],nil,nil)--使用例子
end
end})
end
if not isList then
print(1234)
dialog.setMessage(massge)
end
dialog.setPositiveButton("确定",{onClick=function(v) print"点击了积极按钮"end})
--dialog.setNeutralButton("中立",nil)
dialog.setNegativeButton("返回",{onClick=function(v)
if #G_Data>=2 then
showDialog(true,G_Data[#G_Data-1].title,nil,G_Data[#G_Data-1].keys,G_Data[#G_Data-1].values)--使用例子
G_Data[#G_Data]=nil
end
end})
dialog.show()
end
--写入原始数据
G_Return={keys=keys,values=values,title="_G"}
table.insert(G_Data,G_Return)
-- 调用显示对话框的函数
showDialog(true,"_G",nil,keys,values)
效果演示
弹出的对话框 会分析当前_G全局对象 并且递归调用每一项内部的table用于查看当前环境相关数据
必要情况下可用debug.getinfo 来获取部分的function对象 的字符串内容
应用
知道了这个_G后对我们的开发有什么帮助么?当然是有的!我们可以利用全局变量更好替换原有的变量,或者清除一些原有的变量,这其实就是Hook,比如以自己定义一个print去替换原有的print并在我们自己定义的print函数中做相应的处理然后返回... 具体操作见Lua Hook的文章...
发表评论