suixin812 发表于 2014-5-6 11:26:23

【Lua Snippet】打印_G表

本帖最后由 suixin812 于 2019-11-3 15:14 编辑

Rainmeter 4.0beta r2620
Lua scripting: Corrected an issue where anything defined in the Initialize() function of a Lua script was treated as "global" across all skins using Lua, which could cause "bleeding" of defined variables between skins, or between script measures in a single skin. Each Lua measure will now run in an entirely separate local context.

r2620版本后,不同皮肤和Measure不再共用一个_G表。
无法再通过_G的方式指向另一个Lua Measure实例中的全局变量,
也无法再通过_G表来在多个Lua Measure实例中共享数据。

-------------------------------

我们知道Rainmeter的Lua环境与标准的Lua 5.1环境是不同的,
一些库和函数是被禁用的,比如debug库或require函数。
此外Lua本身不同版本之间也存在某些函数的被废弃的情况。所以,我们可以通过打印_G表来了解哪些函数存在,哪些函数不存在
因为_G表里储存了所有全局变量

下面这段代码向Rainmeter的安装目录中的test.txt打印了_G表中的所有内容
这里不包含_G、_G等储存了Lua Measure实例的全局变量的表

      local gt = { }
                --用来记录_G中所有的表及其键与值
      local fo = io.open('test.txt','w')
                --输出到这个文件
      local unpack_g
                --定义将_G表中的项目记录到gt中的函数
      unpack_g = function (k, v, t, pn)
                if not t or not gt then
                        --函数被初次调用时
                        --形如unpack_g(_, _G, _, '_G')
                        v = v or _G
                        t = v
                        k = 'nil'
                        pn = pn or '_G'
                        gt = gt or {}
                        gt['name'] = pn or '_G'
                end
                --函数被嵌套调用时
                if type(v) == 'bool' then
                        gt['boo'] = gt['boo'] or {}
                        gt['boo'] = tostring(v)
                elseif type(v) == 'number' then
                        gt['num'] = gt['num'] or {}
                        gt['num'] = v
                elseif type(v) == 'string' then
                        gt['str'] = gt['str'] or {}
                        gt['str'] = ('%q'):format(v:sub(1,20))
                elseif type(v) == 'function' then
                        gt['foo'] = gt['foo'] or {}
                        gt['foo'] = 'function()'
                elseif type(v) == 'userdata' then
                        gt['usr'] = gt['usr'] or {}
                        gt['usr'] = 'userdata'
                elseif type(v) == 'table' then
                        gt['tb'] = gt['tb'] or {}
                        if gt and k~='nil' then
                              --键k指向一个gt已经记录了的表
                              --则只记录表的名字
                              gt['tb'] = gt['name']
                        else
                              --键k指向一个gt未记录的表
                              --或当前为函数的初次调用时
                              --则记录这个表及其键与值
                              gt['tb'] = k~='nil' and '{}' or nil
                              if k == 'gt' or (t==_G and type(k) == 'number') then
                                        --不打印当前定义的gt表
                                        --不打印_G等表
                                        return
                              end
                              gt = gt or {}
                              gt['name'] = pn or gt['name']..'['..k..']'
                              t = v
                              for k, v in pairs(t) do
                                        unpack_g(k, v, t)
                                                --嵌套调用unpack_g
                              end
                        end
                end
      end
      --开始记录,从_G表开始
      unpack_g(_, _G, _, '_G')
      --对项目进行排序
      local gti = {}
      for _, p in pairs(gt) do
                table.insert(gti, p)
      end
      table.sort(gti, function(a,b) return a['name'] < b['name'] end)
      --开始打印
      for _, p in ipairs(gti) do
                fo:write(p['name'], '\t=\t{}\n')
                for _, tp in ipairs{'boo', 'num', 'str', 'foo', 'usr', 'tb'} do
                        if p then
                              local ti = {}
                              for k, v in pairs(p) do
                                        table.insert(ti,{tostring(k), v})
                              end
                              table.sort(ti, function(a,b) return a < b end)
                              for _, sp in ipairs(ti) do
                                        fo:write(p['name'], '[', sp,']\t=\t',sp,'\n')
                              end
                        end
                end
                fo:write('\n')
      end
      fo:close()
      fo = nil
      --清空记录,避免垃圾回收障碍
      gt = nil
      gti = nil
其中 gt表的结构为
gt = {      name = '_G',
                num = {}
                num['num1'] = 1,
                num['num2'] = 2
                str = {}
                foo = {}
                tb
      }
下面为打印结果的部分截图





风过秋山 发表于 2014-5-6 14:29:48

真牛!有技术的男人充满魅力啊!

yking1997 发表于 2014-5-9 17:36:41

lua,有时间要学习学习

0。. 发表于 2014-5-9 22:22:23

不明觉厉......

AkaJervis 发表于 2014-5-9 22:31:46

什么东东{:10_443:}

时崎`狂三 发表于 2014-5-13 10:20:43

总感觉很犀利的样子

z6622388 发表于 2015-4-4 14:52:54

q1237 发表于 2015-4-21 17:33:17

{:10_432:}好厉害 下载了

xjzpltz 发表于 2015-5-9 02:46:30

顶一下顶一下顶一下

AVegetarianMing 发表于 2015-7-4 08:30:08

感谢楼主分享            
页: [1] 2 3 4
查看完整版本: 【Lua Snippet】打印_G表