2011-08-22 57 views
1

我嵌入Lua並希望腳本能夠讀取全局表,但不能自動寫入它,因此兩個腳本可以寫入具有相同名稱的變量而不會覆蓋彼此,但仍然能夠添加東西到全局表中。製作全球環境訪問專用(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; 
} 

回答

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 

請注意,這並不能遞歸調用,所以如果您將任何表定義爲全局(甚至是任何內置函數),則內容可以更改,但表本身不能替換。

3

這並不是說要改變__index,它__newindex。另外,您不能使用__index來獲取對錶中存在的密鑰的訪問權限。在所有情況下使表只讀的唯一方法是將所有讀取推遲到代理表並拋出寫入錯誤。