Making global environment access-only (Lua)

别等时光非礼了梦想. 提交于 2019-12-11 05:57:35

问题


I embedded Lua and want scripts to be able to read the global table but not automatically write to it so two scripts can write variables with the same name without overwriting eachother but still being able to add stuff to the global table. I can't really explain it better then this:

Script 1

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

Script 2

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

How I tried to accomplish this is by doing something like this (The 'scripts' being a function)

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

My Lua binding is LuaJ, for the sake of giving all information here is that code too:

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;
}

回答1:


Here's a function I use to return a read-only table:

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

So for your code, you'd have the following:

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

Note that this does not work recursively, so if you have any table defined as a global (or even any of the built-in functions) the contents can be changed, but the table itself cannot be replaced.




回答2:


It's not __index that you want to change, it's __newindex. In addition, you can't use __index to catch access to keys that do exist in the table. The only way to make a table read-only in all situations is to defer all reads to a proxy table and throw an error on writes.



来源:https://stackoverflow.com/questions/7145984/making-global-environment-access-only-lua

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!