Lua学习记录 — (8)模块与包

ModulePackage.lua

------------------------------------ 模块与包 ------------------------------------
------- 模块加载
-- Lua提供了一个名为require的函数来加载模块;
-- require("<模块名>") 或者  require "<模块名>"
-- require查找成功会返回加载器,否则会抛出错误;

--- 加载lua模块(这里myModule.lua放在本xx.lua同目录的module文件夹里)
-- 模块路径:LUA_PATH环境变量
local myMdl = require('module.myModule')
print(myModule.mysin(3.14 / 2))                   --> 0.99999968293183
print(myMdl.name)                                       --> math
say()                                                   --> 你好! (调用了myModule.lua中的sayHello()函数)

--- 加载C包(mylib.dll放在本xx.lua同目录下)
-- C库路径:LUA_CPATH环境变量;
local myLib = require ("mylib")
-- 结果与上面的例子相同,但是这里是通过调用C库中的函数实现;
print(myLib.mysin(3.14 / 2))                            --> 0.99999968293183

------- require( modname )加载机制
--  按顺序执行以下步骤,直到某步骤成功为止;

-- (1) 先查找 package.loaded 表,若 modname 被加载过(即表中存在 modname),则返回
--       package.loaded[modname]中保存的值(即模块);

-- (2) 按照 package.searchers 查找器序列的执行来查找,如下:
--    1. 查找 package.preload 表,若存在 package.preload[modname],则返回这个加载器(这个值是这个函数);
--    2. 查找Lua库的加载库;(按照 package.path 的路径作查找)
--    3. 查找C库的加载库;(按照 package.cpath 的路径作查找)
--    4. 一体化加载器;(按照 package.cpath 路径,如查找模块中的子模块)

-- (3) 调用返回的加载器;(参数1:modname ; 参数2:获取加载器过程中得到的参数)

-- (4) 加载器返回非空值,则将其赋值给 package.loaded[modname];
--       加载器返回空值,则将 package.loaded[modname] 赋值为 true;

-- (5) 加载、运行模块时有错误,或无法为模块找到加载器,require都会抛出错误;

------- package包API解析
-- Lua包管理库帮助从Lua中加载模块,除了require是放在全局环境中,其他的部分都在表package中;

--- package.config:string
-- 一个描述有一些为包管理准备的编译期配置信息的串;
-- 行一:目录分割串;(Windows默认是 '\' ,其他系统是 '/' )
-- 行二:路径分隔符;(默认是 ';' )
-- 行三:模板字符串替代符;(默认是 '?' )
-- 行四:执行程序所在目录的替换符;(Windows默认是 '!' )
-- 行五:忽略记号;(默认是 '-' )(使用loadlib构建luaopen_函数名时,忽略掉'-'后的文本,require支持得不友好)

do
    local str = string.gsub(package.config,"\n"," ")
    print(str)                                          --> \ ; ? ! -
end

--- package.preload:table
-- 保存有一些特殊模块的加载器;
-- 这个变量仅仅是对真正那张表的引用,改变这个值,并不会改变require使用的表;

print(package.preload)                                --> table: 0114FD30

--- package.loaded:table
-- 用于require控制哪些模块已经被加载的表;
-- 这个变量仅仅是对真正那张表的引用,改变这个值,并不会改变require使用的表;

do
    local str = 'package.loaded:'
    local fmt = "'%s' "
    for k, v in pairs(package.loaded) do
        str = str .. fmt:format(k)        --> package.loaded:'io' 'math' 'module.myModule' 'string' 'table' 'os' '_G' 'mylib' 'debug' 'utf8' 'package' 'coroutine'
    end
    print(str)
end

--- package.path:string
-- 这个路径被require在Lua加载器中做搜索时用到;
-- 启动时,Lua用环境变量 LUA_PATH 或 LUA_PATH_5_3 来初始化这个变量;(或者采用luaconf.h中默认的路径)
-- 环境变量中出现的所有';;'都会被替代成默认的路径;

do
    local str = string.gsub(package.path,';',';|')
    print(str)                  --> C:\Program Files (x86)\Lua\5.1\lua\?.luac;|C:\Program Files (x86)\Lua\5.3\?.luac;|.\?.lua;|
end

--- package.cpath:string
-- 这个路径被require在C加载器中做搜索时用到;
-- 启动时,Lua用环境变量 LUA_CPATH 或 LUA_CPATH_5_3 来初始化这个变量;(或者采用luaconf.h中默认的路径)
-- 环境变量中出现的所有';;'都会被替代成默认的路径;

do
    local str = string.gsub(package.cpath,';',';|')
    print(str)                  --> C:\Program Files (x86)\Lua\5.3\?.dll;|C:\Program Files (x86)\Lua\5.3\..\lib\lua\5.3\?.dll;|C:\Program Files (x86)\Lua\5.3\loadall.dll;|.\?.dll
end

--- package.searchers:table
-- 用于require控制如何加载模块的表;
-- 表内每一项都是一个 "查找器函数";(require按次序调用这些 "查找器")
-- 参数: 传入模块名(即require的参数)作为唯一的一个参数;
-- 返回值:
--    1. 查找成功:此函数返回:1个模块的 "加载器" 和 1个传递给这个加载器的参数;
--    2. 查找失败:返回描述失败原因的字符串(或者nil);

-- 查找器序列,如下:

--    1. 查找 package.preload 表(无返回值)
--       a. 过程:若存在 package.preload[modname],这个值就是对应的加载器(这个值是这个函数);

--    2. 查找Lua库的加载库;(返回模块的文件名)
--       a. 路径:package.path;
--       b. 过程:同package.searchpath描述一致,如:
--          myMod.lua在c:\lua\module,环境变量LUA_PATH有路径"c:\lua\?.lua",则参数 modname
--          可以是"module.myMod",会将"."替换成"\",再以"module\myMod"替代"?",即最终路径:
--          "c:\lua\module\myMod.lua";

--    3. 查找C库的加载库;(返回模块的文件名)
--       a. 路径:package.cpath;
--       b. 过程:同package.searchpath描述一致,如:
--          a.b.c-v2.1.dll在c:\lua\clib,环境变量LUA_CPATH有路径"c:\lua\clib\?.dll",则参
--          数 modname可以是"a.b.c-v2.1",将以"a.b.c-v2.1"替代c路径的"?",即最终路径:
--          "c:\lua\clib\a.b.c-v2.1.dll";
--          找到该C库后,首先使用动态链接机制连接该库,然后尝试在该库中寻找可用作加载器的C函数;
--          则个C函数名字必须是"luaopen_"紧接模块名的字符串,即将modname中"-"后面的串去掉,同
--          时,将"."替换成"_",即:"a_b_c",最终函数名:"luaopen_a_b_c"

--    4. 一体化加载器;(返回模块的文件名,如查找模块中的子模块)
--       a. 路径:package.cpath;
--       b. 过程:查找根名字,如:
--          a-v2.1.dll在c:\lua\clib,环境变量LUA_CPATH有路径"c:\lua\clib\?.dll",则参
--          数 modname如果是"a.b.c",将以"a"替代c路径的"?",即最终路径:"c:\lua\clib\a.dll";
--          找到该C库后,接着会在里面找子模块的加载函数,本例子中的加载函数就是"luaopen_a_b_c",
--          当然,里面也会存在"luaopen_a"、"luaopen_a_b"等C函数;
--       c. 特点:可以把若干C子模块打包进单个库,每个子模块都可以有原本的加载函数名;

do
    local str = ''
    local fmt = "k='%s','%s'| "
    for k, v in pairs(package.searchers) do
        str = str .. fmt:format(k,v)        --> k='1','function: 0133BA58'| k='2','function: 013412C8'| k='3','function: 01340CD8'| k='4','function: 013411D8'|
    end
    print(str)
end

--- package.searchpath(name,path[,sep[,rep]])
-- 在指定 path 中搜索指定的 name;
-- 路径:一个包含有一系列以分号分割的 模板 构成的字符串;
-- 模板:即问号("?"),都会用name去替代;
-- sep、rep:将name中的sep符号替换成rep符号;(sep默认为"." rep默认为"\")
-- 返回值:
--    成功:第一个可以用读模式打开(并立即关闭)的文件的名字;
--    失败:nil + 错误消息

do
    local path = ".\\module\\?.lua;.\\?.lua;"
    print(package.searchpath("module.myModule",path))        --> .\module\myModule.lua
    print(package.searchpath("mymodule",path))       --> .\module\myModule.lua  (不区分大小写)
    print(package.searchpath("myXXX",path))       --> nil / no file '.\module\myXXX.lua' / no file '.\myXXX.lua'
end


--- package.loadlib(libname,funcname)
-- 让宿主程序动态链接 C 库 libname;
-- 当funcname为 "*",它仅仅连接该库,并将库中符号导出给其他动态链接库使用;
-- 当funcname为库中函数名,则查找库中对应函数,以C函数形式返回;(funcname要遵循原型lua_CFunction)
-- 相比于require(modname):
--    1. 只加载 C 库;
--    2. 不做任何路径查询;(即不使用 package.searchers 的4个加载器)
--    3. 不会自动加扩展名;(如:"mylib-v2.1.dll"改成"mylib-v2.1",会搜索失败)
--    4. 对忽略记号支持好;(如:在require中传入"mylib-v2.1.dll",会搜索失败)

-- (1) 用法一 :获取库中的模块
--  cpp中函数原型“extern "C" __declspec(dllexport) int luaopen_mylib(lua_State* L)”
openMyLib = package.loadlib("mylib-v2.1.dll","luaopen_mylib")
mylibTable = openMyLib()
print(mylibTable.mysin(3.14/2))                           --> 0.99999968293183

--(2)用法二 :获取库中的某个函数
--  cpp中函数原型“extern "C" __declspec(dllexport) int l_sin(lua_State *L)”
mysin = package.loadlib("mylib.dll","l_sin")
print(mysin(3.14/2))                                      --> 0.99999968293183

myModule.lua

--[=[
1. Lua的模块是由变量、函数等已知的元素组成的table;
2. 要创建一个模块,只需要创建一个table,然后把需要到处的变量、函数等放入其中,最后返回这个table就行;
]=]

-- 定义一个模块
myModule = {}

-- 定义一个模块的函数
function myModule.mysin(num)
    return math.sin(num)
end

-- 定义一个私有函数(仅模块内可以访问)
local function sayHello()
    print("你好!")
end

-- 定义一个公有的函数,用以调用私有函数
function say()
    sayHello()
end

-- 定义一个变量
myModule['name'] = 'math'

-- 结尾处返回这个模块的table
return myModule
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Nginx中配置Lua模块,你需要遵循以下步骤: 1. 在安装Nginx之前,请确保你已经安装了LuaJIT或者Lua的开发库。你可以通过在终端中运行以下命令来安装它们: 对于Ubuntu/Debian系统: ``` sudo apt-get install libluajit-5.1-dev ``` 对于CentOS/RHEL系统: ``` sudo yum install lua-devel ``` 2. 下载Nginx的源码,并解压缩它。 3. 在解压缩后的目录中,运行以下命令来配置编译选项,其中`--prefix`是安装目录的路径: ``` ./configure --prefix=/path/to/install --add-module=/path/to/nginx-lua-module ``` 请将`/path/to/nginx-lua-module`替换为你实际安装Lua模块的路径。 4. 运行以下命令编译和安装Nginx: ``` make sudo make install ``` 5. 配置Nginx以使用Lua模块。在Nginx的配置文件(通常是`nginx.conf`)中添加以下内容: ``` http { lua_package_path "/path/to/lua-scripts/?.lua;;"; lua_package_cpath "/path/to/lua-modules/?.so;;"; server { ... location / { ... content_by_lua_file /path/to/lua-script.lua; } } } ``` 请将`/path/to/lua-scripts`替换为你实际存放Lua脚本的路径,将`/path/to/lua-modules`替换为你实际存放Lua模块的路径,将`/path/to/lua-script.lua`替换为你实际的Lua脚本文件路径。 6. 保存并关闭配置文件后,重新启动Nginx服务。你现在应该可以在浏览器中访问配置的Lua脚本了。 这些步骤涵盖了在Nginx中配置Lua模块的基本过程。请根据你自己的需求进行相应的调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值