Как сделать глобальные переменные неизменяемыми в Lua/LuaJ?

Описание

Я делаю программу LuaJ, и вот такой скрипт lib:

function foo()
    print("foo");
end

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

Например, вот сценарий 1:

foo = function()
    print("bar");
end

а вот скрипт 2:

foo();

Что сделано

Я видел эти два вопроса. Они работают, но не решают эту проблему.

LuaJ Как избежать переопределения существующих записей в таблице Globals

Предотвращение переопределения функций в таблице Lua

Предоставление доступа только к глобальной среде (Lua)


Я пытался загружать lib каждый раз, когда запускал скрипт или устанавливал local _ENV, но из-за того, что могут быть дополнительные обратные вызовы с Java на Lua, это не работает правильно.

Теперь я справляюсь с этим, создавая Globals и загружая скрипт lib каждый раз, когда загружаю скрипт на Java следующим образом:

    public static void main(String[] args) {
        loadAndCallViaDifferentEnv(libPath, script1);
        loadAndCallViaDifferentEnv(libPath, script2);
    }

    static void loadAndCallViaDifferentEnv(String libPath, String scriptPath) {
        Globals globals = JsePlatform.standardGlobals();
        globals.loadfile(libPath).call();
        globals.loadfile(scriptPath).call();
    }

Работает хорошо, но стоит дорого. Есть ли способ лучше?


person Jennifer brown    schedule 31.05.2021    source источник


Ответы (1)


Я предполагаю, что вы хотите защитить три функции от перезаписи: foo1, foo2 и print

-- define foo1 and foo2 inside protected table instead of as usual globals
local protected = {}

function protected.foo1()  
   print("foo1");
end

function protected.foo2()
   print("foo2");
end

-- if a function to be protected already exists, remove it from globals:
protected.print = print
print = nil

-- Now set the metatable on globals
setmetatable(_G, {
   __index = protected,
   __newindex =
      function(t, k, v)
         if not protected[k] then
            rawset(t, k, v)
         end
      end
})

Теперь вы можете вызывать foo1, foo2 и print из других модулей без require, но не можете перезаписать их:

-- the script 1:
foo1 = function()
   print("bar");
end
foo1();   -- original protected.foo1() is invoked
-- the script 2:
foo1();   -- original protected.foo1() is invoked
person Egor Skriptunoff    schedule 01.06.2021