Обеспечение доступа к глобальной среде (Lua) - PullRequest
1 голос
/ 22 августа 2011

Я встроил 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 ]

3 голосов
/ 22 августа 2011

Это не __index, что вы хотите изменить, это __newindex. Кроме того, вы не можете использовать __index для получения доступа к ключам, которые существуют в таблице. Единственный способ сделать таблицу доступной только для чтения во всех ситуациях - это отложить все чтения в прокси-таблицу и выдать ошибку при записи.

2 голосов
/ 22 августа 2011

Вот функция, которую я использую для возврата таблицы только для чтения:

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

Обратите внимание, что это не работает рекурсивно, поэтому, если у вас есть какая-либо таблица, определенная как глобальная (или даже любая из встроенных функций), содержимое может быть изменено, но сама таблица не может быть заменена.

...