使全局环境仅可访问(Lua)

发布于 2024-11-30 21:45:59 字数 947 浏览 0 评论 0原文

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小镇女孩 2024-12-07 21:45:59

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

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.

风流物 2024-12-07 21:45:59

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文