一个程序,用于启用默认变量的本地

时间:2016-02-09 23:23:49

标签: variables lua computercraft

所以我对Lua中的全局默认样式感到恼火。我正在尝试编写一个程序,它将使所有程序在无法创建全局变量之后运行。当他们尝试时,该变量将被设置为该程序的功能环境。我想出了这个,它似乎工作,但由于某种原因在ComputerCraft rom / programs / edit中的[edit:9]中抛出一个错误。当我运行测试程序时,

a = 1
print(a)

它工作正常并且阻止创建全局变量,同时仍然允许该程序访问它,但它不适用于其他程序。我已经尝试过_G.a,本地a等等,但所有这些都有效。有没有人知道为什么它可能不适用于其他程序?

local oldload = loadfile
function _G.loadfile(str)
  local func = oldload(str)
  local env = {}
  env._G = env
  setmetatable(env, {__index = _G, __newindex = 
    function(table, var, val)
      rawset(env, var, val)
    end})
  setfenv(func, env)
  return func
end

2 个答案:

答案 0 :(得分:1)

Lua旨在成为一种嵌入式语言。这意味着最终仲裁者是主语C。

一个Lua脚本可以通过沙盒技术实现对另一个的支配。您没有完全沙箱脚本。您更改了loadfile,但未更改loaddofile

但这没关系。为什么?因为在支配地位方面, C总是赢得。请参阅,C不会调用Lua loadfile函数。嗯,显然可以,但通常不会。相反,它调用Lua API luaL_loadfile

Lua代码可以为其直接加载的其他Lua代码建立沙箱。但是基于Lua的沙箱对C代码没有影响,除非该代码被故意设计为生活在Lua沙箱中。大多数C库都没有。

这意味着,一旦您决定在无法控制的C执行环境中运行,您的Lua沙箱就意味着什么。 C代码可以(在许多情况下)将脚本加载到您的控件之外,并为它们提供所需的任何环境。

从Lua那里你无能为力。解决此问题的唯一方法是修改Lua .dll本身以建立沙箱。

答案 1 :(得分:0)

我找到了解决方案。事实证明,shell API(许多ComputerCraft程序中使用的API)不在_G中,因此在应用沙箱时无法访问。这是我的新功能代码:

local oldload = load
function _G.load(str, arg1, arg2, arg3)
  local func = oldload(str, arg1, arg2, arg3)
  local env = getfenv(func)
  if (env == _G) then
    env = {}
    env._G = env
  end
  setmetatable(env, {__index = _G, __newindex = function(table, var, val) rawset(env, var, val) end})
  setfenv(func, env)
  return func
end