lua 13 模块(类似class)与包
转自:
http://www.runoob.com/lua/lua-modules-packages.html
模块类似于一个封装库,从 Lua 5.1 开始,Lua 加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。
Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行。以下为创建自定义模块 module.lua,文件代码格式如下:
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {} -- 定义一个常量
module.constant = "这是一个常量" -- 定义一个函数
function module.func1()
io.write("这是一个公有函数!\n")
end local function func2()
print("这是一个私有函数!")
end function module.func3()
func2()
end return module
由上可知,模块的结构就是一个 table 的结构,因此可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数。
上面的 func2 声明为程序块的局部变量,即表示一个私有函数,因此是不能从外部访问模块里的这个私有函数,必须通过模块里的公有函数来调用.
require 函数
Lua提供了一个名为require的函数用来加载模块。要加载一个模块,只需要简单地调用就可以了。例如:
require("<模块名>")
或者
require "<模块名>"
执行 require 后会返回一个由模块常量或函数组成的 table,并且还会定义一个包含该 table 的全局变量。
-- test_module.lua 文件
-- module 模块为上文提到到 module.lua
require("module") print(module.constant) module.func3()
以上代码执行结果为:
这是一个常量
这是一个私有函数!
或者给加载的模块定义一个别名变量,方便调用:
-- test_module2.lua 文件
-- module 模块为上文提到到 module.lua
-- 别名变量 m
local m = require("module") print(m.constant) m.func3()
以上代码执行结果为:
这是一个常量
这是一个私有函数!
加载机制
对于自定义的模块,模块文件不是放在哪个文件目录都行,函数 require 有它自己的文件路径加载策略,它会尝试从 Lua 文件或 C 程序库中加载模块。
require 用于搜索 Lua 文件的路径是存放在全局变量 package.path 中,当 Lua 启动后,会以环境变量 LUA_PATH 的值来初始这个环境变量。如果没有找到该环境变量,则使用一个编译时定义的默认路径来初始化。
当然,如果没有 LUA_PATH 这个环境变量,也可以自定义设置,在当前用户根目录下打开 .profile 文件(没有则创建,打开 .bashrc 文件也可以),例如把 "~/lua/" 路径加入 LUA_PATH 环境变量里:
#LUA_PATH
export LUA_PATH="~/lua/?.lua;;"
文件路径以 ";" 号分隔,最后的 2 个 ";;" 表示新加的路径后面加上原来的默认路径。
问号就是下面的module!
接着,更新环境变量参数,使之立即生效。
source ~/.profile
这时假设 package.path 的值是:
/Users/dengjoe/lua/?.lua;./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua
那么调用 require("module") 时就会尝试打开以下文件目录去搜索目标。
/Users/dengjoe/lua/module.lua;
./module.lua
/usr/local/share/lua/5.1/module.lua
/usr/local/share/lua/5.1/module/init.lua
/usr/local/lib/lua/5.1/module.lua
/usr/local/lib/lua/5.1/module/init.lua
如果找过目标文件,则会调用 package.loadfile 来加载模块。否则,就会去找 C 程序库。
搜索的文件路径是从全局变量 package.cpath 获取,而这个变量则是通过环境变量 LUA_CPATH 来初始。
搜索的策略跟上面的一样,只不过现在换成搜索的是 so 或 dll 类型的文件。如果找得到,那么 require 就会通过 package.loadlib 来加载它。
C 包
Lua和C是很容易结合的,使用C为Lua写包。
与Lua中写包不同,C包在使用以前必须首先加载并连接,在大多数系统中最容易的实现方式是通过动态连接库机制。
Lua在一个叫loadlib的函数内提供了所有的动态连接的功能。这个函数有两个参数:库的绝对路径和初始化函数。所以典型的调用的例子如下:
local path = "/usr/local/lua/lib/libluasocket.so"
local f = loadlib(path, "luaopen_socket")
loadlib函数加载指定的库并且连接到Lua,然而它并不打开库(也就是说没有调用初始化函数),反之他返回初始化函数作为Lua的一个函数,这样我们就可以直接在Lua中调用他。
如果加载动态库或者查找初始化函数时出错,loadlib将返回nil和错误信息。我们可以修改前面一段代码,使其检测错误然后调用初始化函数:
local path = "/usr/local/lua/lib/libluasocket.so"
-- 或者 path = "C:\\windows\\luasocket.dll",这是 Window 平台下
local f = assert(loadlib(path, "luaopen_socket"))
f() -- 真正打开库
一般情况下我们期望二进制的发布库包含一个与前面代码段相似的stub文件,安装二进制库的时候可以随便放在某个目录,只需要修改stub文件对应二进制库的实际路径即可。
将stub文件所在的目录加入到LUA_PATH,这样设定后就可以使用require函数加载C库了。
lua 13 模块(类似class)与包的更多相关文章
- Python 入门基础13 --模块与包
本节内容: 一.模块及使用 1.模块及使用 2.起别名.from导入 3.自执行与模块 二.包的使用 2.1 包中模块的使用:import 2.2 包的嵌套 2.3 包中模块的使用:from ...i ...
- lua对模块接口扩展的一种方法
module lua中模块的实现,对于使用者来说就是一个库,引用此库后,可以调用库中实现的任意函数. 使用库,可以将一类功能相关的接口做封装,并提供开放接口. 参考: http://blog.codi ...
- Lua中模块初识
定义了两个文件: Module.lua 和 main.lua 其中,模块的概念,使得Lua工程有了程序主入口的概念,其中main.lua就是用来充当程序主入口的. 工程截图如下: Module.lua ...
- 铁乐学Python_Day34_Socket模块2和黏包现象
铁乐学Python_Day34_Socket模块2和黏包现象 套接字 套接字是计算机网络数据结构,它体现了C/S结构中"通信端点"的概念. 在任何类型的通信开始之前,网络应用程序必 ...
- struct 模块解决 TCP黏包问题
首先来看一下产生黏包现象的一段代码: # server.py 服务端 import socket sk = socket.socket() sk.bind(('127.0.0.1',9000)) ...
- lua不同模块调用
一.起因 由于准备把lua加入的系统中,还需把字符串解析json.下了个json的lua,目前还没有搞定.但是一个lua,调用其他lua文件模块,目前刚刚搞定. 暂作记录. 二. 模块调用测试 1. ...
- 通过开启子进程的方式实现套接字服务端可以并发的处理多个链接以及通讯循环(用到了subprocess模块,解决粘包问题)
今日作业:通过开启子进程的方式实现套接字服务端可以并发的处理多个链接以及通讯循环(用到了subprocess模块,解决粘包问题) server(服务端) import socket from mult ...
- Go1.13 标准库的 http 包爆出重大 bug,你的项目中招了吗? 原创: 王亚楼 Go语言中文网 今天
Go1.13 标准库的 http 包爆出重大 bug,你的项目中招了吗? 原创: 王亚楼 Go语言中文网 今天
- python基础】——python添加模块搜索路径和包的导入
方法一:函数添加1 import sys2 查看sys.path3 添加sys.path.append("c:\\") 方法二:修改环境变量w用户可以修改系统环境变量PYTHONP ...
随机推荐
- mysql语法总结及例子
1. DDL相关 a. -- 查询所有数据库 show databases;-- 删除数据库drop database ladeng; b. -- use `数据库名称`; 表示使用此数据库 use ...
- vue预览本地图片
<template> <div> <a href="javascript:void(0);" @change="addImage" ...
- LG2145 「JSOI2007」祖码 区间DP
问题描述 LG2145 题解 把颜色相同的一段看做一个点. 然后类似于合唱队区间DP即可. 但是这题好像出过一些情况,导致我包括题解区所有人需要特判最后一个点. \(\mathrm{Code}\) # ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) D2. Optimal Subsequences (Hard Version) 数据结构 贪心
D2. Optimal Subsequences (Hard Version) This is the harder version of the problem. In this version, ...
- COM 编程基础
DirectX 采用了 COM 标准.而 DirectShow 是一套完全基于 COM 的应用系统.要想深入学习 DirectShow,掌握一些 COM 编程的基础知识是必不可少的. 一.COM 是什 ...
- Tensorflow分布式部署和开发
关于tensorflow的分布式训练和部署, 官方有个英文的文档介绍,但是写的比较简单, 给的例子也比较简单,刚接触分布式深度学习的可能不太容易理解.在网上看到一些资料,总感觉说的不够通俗易懂,不如自 ...
- spring cloud 2.x版本 Config配置中心教程
前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前面的文章eureka-server的实现. 参考 eureka-server ...
- LeetCode 202: 快乐数 Happy Number
题目: 编写一个算法来判断一个数是不是 "快乐数". 一个 "快乐数" 定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直 ...
- SpringBoot系列之profles配置多环境(篇二)
SpringBoot系列之profles配置多环境(篇二) 继续上篇博客SpringBoot系列之profles配置多环境(篇一)之后,继续写一篇博客进行补充 写Spring项目时,在测试环境是一套数 ...
- 05爬虫-requests模块基础(2)
今日重点: 1.代理服务器的设置 2.模拟登陆过验证码(静态验证码) 3.cookie与session 4.线程池 1.代理服务器的设置 有时候使用同一个IP去爬取同一个网站,久了之后会被该网站服务器 ...