探访lua5.2新特性及package机制模拟

探访lua5.2新特性及package机制模拟

项目客户端脚本全面升级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更灵活, 更强大

你可能感兴趣的:(探访lua5.2新特性及package机制模拟)