1

我嵌入了 Lua 并希望脚本能够读取全局表但不能自动写入它,因此两个脚本可以写入具有相同名称的变量而不会相互覆盖但仍然能够向全局表添加内容。我真的不能更好地解释它:

脚本 1

var1 = "foo"
_G.var2 = "bar"

脚本 2

print(var1) -- Prints nil
print(var2) -- Prints 'bar'

我试图通过做这样的事情来实现这一点(“脚本”是一个函数)

newScript = function(content)
    Script = loadstring(content)()
    env = setmetatable({},{__index = _G})
    setfenv(Script,env)
    return Script
end

我的 Lua 绑定是 LuaJ,为了在此处提供所有信息,该代码也是:

private LuaValue newScript(String content){
        LuaTable envMt = new LuaTable();
        envMt.set(INDEX, _G);
        LuaTable env = new LuaTable();
        env.setmetatable(envMt);

        LuaClosure func = (LuaClosure) _G.get("loadstring").call(valueOf(content));

        thread = new LuaThread(func,env);
        thread.resume(NIL);
        return thread;
}
4

2 回答 2

3

不是__index你想改变,而是__newindex。此外,您不能使用__index来捕获对表中确实存在的键的访问。在所有情况下使表只读的唯一方法是将所有读取推迟到代理表并在写入时抛出错误。

于 2011-08-22T10:33:01.367 回答
2

这是我用来返回只读表的函数:

function ro_table (t)
  local t = t
  if t then
    return setmetatable({}, 
      { __index=t, 
        __newindex= function(_,_,_) error ("Attempt to modify read-only table") end, 
      })
  else
    return nil
  end
end

因此,对于您的代码,您将拥有以下内容:

newScript = function(content)
    Script = loadstring(content)()
    setfenv(Script,ro_table(_G))
    return Script
end

请注意,这不能递归工作,因此如果您将任何表定义为全局(甚至是任何内置函数),则可以更改内容,但不能替换表本身。

于 2011-08-22T11:52:42.550 回答