我开始使用C++/Lua
代码库,这有点乱,当我在应用程序执行过程中转储_G
的内容时,我确信有数百个变量只是在某处初始化,但不再在代码中的任何其他位置使用。为了清理它,我想设置一种机制,只要Lua
访问全局变量就会记录。
这是我对如何实现这一点的想法 - 我想设置一个代理_G
,它只能通过__index
和__newindex
将所有读写访问传递给自己的副本原_G
。但是这个简单的脚本不起作用,只输出:
C:\Programs\lua-5.1.5_Win32_bin\lua5.1: error in error handling
GProx =
{
vars = _G
}
setmetatable(GProx, {
__index = function (t, name)
print("Read> " .. name)
return t.vars[name]
end,
__newindex = function (t, name, val)
print("Write> " .. name .. ' = ' .. val)
t.vars[name] = val
end
})
setfenv(0, GProx)
a = 1 --> Expected to print 'Write> a'
print(a) --> Expected to print 'Read> print', 'Read> a', and '1'
这是一个好方法还是有更好的方法来做到这一点? 如果这是一个有效的思路,那么我的代码片段有什么问题?
答案 0 :(得分:3)
您可以直接在_G
表格上设置元表,如PIL section 14.2中所述,所以您非常接近。网上还有一些现有的Lua模块可以做到这一点(也许penlight包含一个)。
答案 1 :(得分:3)
请尝试使用此代码段,它将与读取和写入一起使用:
do
-- Use local variables
local old_G, new_G = _G, {}
-- Copy values if you want to silence logging
-- about already set fields (eg. predeclared globals).
-- for k, v in pairs(old_G) do new_G[k] = v end
setmetatable(new_G, {
__index = function (t, key)
print("Read> " .. tostring(key))
return old_G[key]
end,
__newindex = function (t, key, val)
print("Write> " .. tostring(key) .. ' = ' .. tostring(val))
old_G[key] = val
end,
})
-- Set it at level 1 (top-level function)
setfenv(1, new_G)
end
以下是这些变化的概述:
_G
进行本地引用。在您提议的实现中,如果设置了名为vars
的全局变量,它将覆盖GProx.vars
并中断代理。key
和val
应在打印前通过tostring
,因为大多数值(即表格)都不会隐式转换为字符串。1
级别的环境通常就足够了,不会破坏Lua的内部工作。