[转载]lua5.2 require实现

项目客户端脚本全面升级lua5.2 这是自06年后最大的一次主干更新, 带来的机制, 函数变化也是非常不错的
1. 去掉了全局性质的setfenv/getfenv系列函数, 语言层面提供_ENV语法糖, 这东西跟:操作符一样, 只存在于编译期.

官方建议自己实现module/require/package机制, 毕竟原生这套机制实现太弱智了..

2. 提供了无符号访问函数

3. 更多的lua api变化. 如果想兼容lua5.1的写法, 可以参考luabridge内LuaHelpers.h的实现

以下是本人使用lua5.2实现的一套package机制, 供大家参考

package = {}

-- 读取标记
package.loaded = {}

-- 搜索路径数组
package.path = {} 
package.access =
{
  ["string"] = string,
  ["print"] = print,
  ["table"] = table,
  ["assert"] = assert,
  ["error"] = error,
  ["pairs"] = pairs,
  ["ipairs"] = ipairs,
  ["tonumber"] = tonumber,
  ["tostring"] = tostring,
  ["type"] = type,
  ["math"] = math,
}

local function getreadablepath( name, pathlist )
  for _, path in ipairs(pathlist) do
    local fullpath = path .. "/" .. name .. ".lua"
    local f = io.open( fullpath )
    if f then
      f:close()
      return fullpath
    end
  end
return nil
end


function package.import( name )
  -- 已经读取的直接返回
  local existedenv = package.loaded[name]
  if existedenv then
    return existedenv
  end
  local access = package.access
  -- 设置访问控制权限
  local meta = 
  {
    __index = function( tab, key ) 
      -- 优先取包的空间
      local v = rawget( tab, key )
      if v then
        return v
      end 
      -- 找不到时,从可访问的权限表中查找
      return access[key] 
    end
  }
  -- 初始化一个包的全局环境, 并设置访问方法
  local env = setmetatable( {} , meta )
  --
  local readablepath = getreadablepath( name, package.path )
  if not readablepath then
    error(string.format("package '%s' not found \n%s", name, table.concat( package.path, "\n" ) ) )
  end 
  local func = loadfile( readablepath, "bt", env )
  if type(func) ~= "function" then
    return nil
  end
  -- 设置标记
  package.loaded[name] = env
  -- 执行全局空间
  func( )

  return env
end
package.path = {"E:/Download/t"}
local m = package.import "m"
m.foo()
以下是m模块(m.lua)的内容
function foo( )
print("转载注明: 战魂小筑 http://www.cppblog.com/sunicdavy", io ) 
end

 


测试结果中, io打印出nil, 显示权限已经被控制住
本package设计比原生package更灵活, 更强大

posted on 2016-03-29 13:39  He2Li  阅读(879)  评论(0)    收藏  举报