代码之家  ›  专栏  ›  技术社区  ›  ensonic

lua环境和模块

  •  4
  • ensonic  · 技术社区  · 8 年前

    假设我有一个模块:

    -- env.lua
    
    local env = {}
    
    function env.resolve(str)
      print("mod", _ENV)
    
      if _resolve_path ~= nil then
        return _resolve_path(str)
      else
        error("bad env")
      end
    end
    
    return env
    

    以及一些使用它的代码:

    -- sandbox demo
    -- run as: lua env-test.lua
    
    env = require('env')
    
    function _resolve_path(path)
      return "/" .. path
    end
    
    print("before main()")
    print("", _ENV)
    print("", env.resolve("test"))
    
    local sandbox
    do
      local _ENV = {
        print = print,
        env = env,
        _resolve_path = function (path)
          return "/chroot/" .. path
        end
      }
      function sandbox()
        print("from sandbox()")
        print("", _ENV)
        print("", env.resolve("test"))
      end
    end
    
    sandbox()
    
    print("after main()")
    print("", _ENV)
    print("", env.resolve("test"))
    

    我想实现的是 env.resolve() from sandbox()将使用环境中的自定义resolve_path函数。但它可以看到,环境并没有应用于从沙盒函数调用的代码。其目的是根据从何处调用模块来预测某些模块的行为。E、 g.具有具有不同本地_resolve_path()函数的沙盒{1,2,3}()。

    1 回复  |  直到 7 年前
        1
  •  3
  •   Community Egal    7 年前

    当您将模块加载到 require 它与全球环境息息相关。一旦在一个环境中创建了一个函数,它就会在其整个生命周期内拥有该环境。

    在Lua 5.2之前,您可以使用 set/getfenv 改变环境,但环境现在是词汇化的。只有通过更改 _ENV 增值。

    那么,如何在不同的环境中运行相同的功能呢?可以将环境作为参数传入:

    function env.resolve(str, _ENV)
      print("mod", _ENV)
      if _resolve_path ~= nil then
        return _resolve_path(str)
      else
        error("bad env")
      end
    end
    

    然后你打电话到哪里 resolve 例如:

    env.resolve('test', _ENV)
    

    或者,如果您希望不必为每个 决定 调用可以绑定 决定 每个新环境的功能:

    -- env.lua
    local print = print
    local error = error
    local env = {}
    
    -- this is the actual resolve function that takes the environment as a parameter
    local function resolve_env(str, _ENV)
      print("mod", _ENV)
      if _resolve_path ~= nil then
        return _resolve_path(str)
      else
        error("bad env")
      end
    end
    
    -- this is the module (ie. global) resolve
    function env.resolve(str)
      return resolve_env(str, _ENV)
    end
    
    -- this function binds a resolve function to a sandbox environment
    function env.bind(_ENV)
      _ENV.env = {
        resolve = function(str)
          return resolve_env(str, _ENV)
        end
      }
      return _ENV
    end
    
    return env
    

    沙盒现在可以设置绑定解析:

    -- sandbox.lua
    env = require 'env'
    
    function _resolve_path(path)
      return "/" .. path
    end
    
    print("before main()")
    print("", _ENV)
    print("", env.resolve("test"))
    
    local sandbox; do
      local _ENV = env.bind{
        print = print,
        _resolve_path = function (path)
          return "/chroot/" .. path
        end
      }
    
      function sandbox()
        print("from sandbox()")
        print("", _ENV)
        print("", env.resolve("test"))
      end
    end
    
    sandbox()
    
    print("after main()")
    print("", _ENV)
    print("", env.resolve("test"))
    

    这将产生以下结果:

    $ lua sandbox.lua
    before main()
            table: 00612f40
    mod     table: 00612f40
            /test
    from sandbox()
            table: 0061c7a8
    mod     table: 0061c7a8
            /chroot/test
    after main()
            table: 00612f40
    mod     table: 00612f40
            /test