我正在学习罗伯托·伊鲁萨利姆希的《Lua编程》,在书中发现沙箱示例使用setfenv()
函数来更改给定函数的环境,但在lua 5.2中,此函数不再可用。
我尝试从文件(配置文件)加载一些值到表中的字段中,但在lua 5.2中,我不能使用setfenv
(所以无法在给定环境中加载值)。阅读了一些关于lua 5.2的文章后,我发现每个函数可能有(也可能没有)一个名为_ENV的upvalue,用作环境。因此,我尝试了以下代码:
function sandbox(sb_func, sb_env)
if not sb_func then return nil, "sandbox function not valid" end
sb_orig_env = _ENV
_ENV = sb_env -- yes, replaces the global _ENV
pcall_res, message = pcall( sb_func )
local modified_env = _ENV -- gets the environment that was used in the pcall( sb_func )
_ENV = sb_orig_env
return true, modified_env
end
function readFile(filename)
code = loadfile(filename)
res, table = sandbox(code, {})
if res then
--[[ Use table (modified_env) ]]--
else
print("Code not valid")
end
将 'sandbox' 函数中的 _ENV
替换掉可以正常工作(无法访问常规字段),但是当执行 'code' 时,它似乎忽略了我替换的 _ENV
,仍然可以访问常规字段(如 print、loadfile、dofile 等)。
阅读更多资料后,我发现 lua 5.2 提供了一个用于此目的的函数,该函数是 loadin(env, chunk)
,其在给定的环境中运行给定的代码块,但是当我尝试将此函数添加到我的代码时,该函数不存在(不在全局 _G
字段中)。
希望能得到一些帮助。
load
和loadfile
中更改环境的这种方法更好,因为setfenv
主要用于加载的代码,所以...谢谢!我已按预期进行了沙盒处理。 - Daniel Rivas_ENV
局部于代码块;对_ENV
的赋值会影响该代码块的局部变量,这是两个闭包共享的上值。 - Miles