壹影博客.
我在下午4点钟开始想你
Lua全局对象 _G详细介绍及应用分享
  • 2023-10-31日
  • 0评论
  • 12763围观

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的文章...

发表评论