【问题标题】:Making global environment access-only (Lua)使全局环境只能访问(Lua)
【发布时间】:2011-08-22 10:18:21
【问题描述】:

我嵌入了 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;
}

【问题讨论】:

    标签: lua luaj


    【解决方案1】:

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

    【讨论】:

      【解决方案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
      

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

      【讨论】:

        猜你喜欢
        • 2017-01-08
        • 1970-01-01
        • 2016-05-11
        • 1970-01-01
        • 1970-01-01
        • 2018-02-08
        • 1970-01-01
        • 1970-01-01
        • 2014-08-05
        相关资源
        最近更新 更多