(原) 简单学习Lua

原创文章,请后转载,并注明出处。

非常小巧的语言,在单片机、go相关库、游戏脚本等都遇到过。快速学习一下。

最新版本5.4,源代码相当小

在ubuntu下编译: make linux test 然后安装 make install

直接运行lua则在窗口中即时运行,也可以lua xx.lua运行代码。

它是一个区分大小写的语言

注释

– 单行注释

–[[   多行注释 ]]–

变量

默认情况下,变量总是全局的。

没有初始化的变量值为nil

删除变量,则是赋值为nil

变量类型

nil

boolean

number 双精浮点

string 字串,双引号或单引号

function 函数

userdata

thread 独立线程

table 表

通过type可以给出变量类型 print(type(10.4))

nil作比较时应该加上双引号 type(x)==“nil”

flase和nil为false,其它均为true,数字0也是true

对数字字符串进行算术操作时,会尝试转换为数字进行运算

print("2"+6)   返回8.0
print("2+5")   返回2+5
print("2"+"6") 返回8.0

字符串连接使用..

print("a".."b")
print(1223..456)

#计算字符串长度 print(#len)

local tab1 = {}   --创建一个空表(局部变量)

local tab2 = {"apple", "pear"}
a = {}
a["key"] = "value"
key = 10
a[key] = 22
a[key] = a[key] + 11
for k, v in pairs(a) do
    print(k .. " : " .. v)
end

运行结果:

10 : 33
key : value

默认初始索引一般以 1 开始

local tbl = {"apple", "pear", "orange", "grape"}
for key, val in pairs(tbl) do
    print("Key", key)
end

table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil。

函数可以存在变量里

可以以匿名函数的方式通过参数传递

Lua变量有三种:全局、局部、表中的域

赋值

a,b = 10, 2*x 对多个变量同时赋值

x, y = y, x 交换xy

控制

while(true)
do
end
if(0)   --0为true
then
end

函数

可以将函数作为参数传递给函数

function add(…) –可变参数

function add(...)
  local s = 0
  for i,v in ipairs{...} do
     s = s + v
  end
  return s
end

do 
    function foo(...)
        for i = i, select('#', ...) do    --获取参数总数
            local arg = select(i, ...);  --读取参数
            print("arg", arg);
        end
    end
end

Lua运算

% 取余

~= 不等于

and or not

.. 连接字符串

# 字符串或表的长度

Lua字符

单引号、双引号、[[]]号

\r \n \0

string.upper 转大写

string.lower 转小写

string.gsub(mainString,findString,replaceString,num) 替换

string.find(str,substr,[init,[end]]) 搜索

string.reverse(arg) 字符反转

string.format() 格式化字符串

string.char(arg) 整数转字符

string.byte(arg[,int]) 转字符为整数

string.len(arg) 长度

string.rep(string,n) 拷贝n次字符串

string.gmatch(str,pattern) 迭代器函数

string.match(str,pattern,init) 寻找匹配

string.sub(s, i [,j]) 字符串截取

数组

array = {"a","b"}

for i = 0, 2 do
    print(array[i])
end

输出nil a b

迭代器

迭代函数ipairs,用于遍历数组的每一个元素

table

用来帮助我们创建不同的数据类型,如数组、字典等

mytable = {} 初始化表
mytable[1] = "Lua"  指定值
mytable = nil 移除引用,lua会释放内存

table.concat(table[,sep[,start[,end]]]) 连接

table.insert(table,[pos,]value ) 插入元素

table.remove(table[,pos]) 移除元素

table.sort() 排序

模块与包

模块类似于封装库

Lua的模块是由变量、函数等已知元素组成的table。

-- module.lua
-- 定义一个名为module的模块
module = {}
--定义一个常量
module.constant = "这是一个常量"
--定义一个函数
function module.func1()
  io.write("这是一个公有函数!\n")
end
local function func2()
  print("这是一个私有函数!")
end

require("<模块名>") 加载模块

requeire “<模块名>”

执行require后会返回一个由模块常量或函数组成的table

require("module")
print(module.constant)
module.func3()

local m = require("module") --别名变量
print(m.constant)
m.func3()

加载机制

加载模块的路径存放在全局变量package.path中。当lua启动后,会以环境变量LUA_PATH的值来初始化这个变量。

C包

与Lua中写包不同,C包在使用前必须首先加载并连接

Lua在一个叫loadlib的函数内提供了所有的动态连接的功能。

local path = "/usr/local/libluasocket.so"
local f = loadlib(path, "luaopen_socket")
f() --真正打开库

协同程序 coroutine

线程和协同程序的区别:线程各自独立,协程需要彼此协作运行。与其它协程共享全局变量和其它大部分东西。

coroutine.create() 创建

coroutine.resume() 重启

coroutine.yield() 挂起

coroutine.status() 查看状态

coroutine.wrap() 创建,同create

coroutine.running() 返回正在运行的协程

co = coroutine.create(
    function(i)
        print(i);
    end
)
 
coroutine.resume(co, 10)   -- 10   启用协程
print(coroutine.status(co))  -- dead
 
print("----------")
 
co = coroutine.wrap(
    function(i)
        print(i);
    end
)
 
co(1) --运行协程,输出1
 
print("----------")
 
co2 = coroutine.create(
    function()
        for i=1,10 do
            print(i)
            if i == 3 then
                print(coroutine.status(co2))  --running
                print(coroutine.running()) --thread:XXXXXX
            end
            coroutine.yield() --挂起,后续暂不执行
        end
    end
)
 
coroutine.resume(co2) --1 恢复
coroutine.resume(co2) --2
coroutine.resume(co2) --3
 
print(coroutine.status(co2))   -- suspended
print(coroutine.running())
 
print("----------")

IO

file = io.open(filename [, mode])

r 只读 w 只写 a 添加 r+ 打开可读写 w+ 清除可读写 a+ 添加可读写 b 二进制

简单模式

file = io.open("test.lua","r")
io.input(file) --设置默认输入文件为test.lua
print(io.read()) --输出文件第一行
io.close(file)

io.tmpfile() 返回一个临时文件句柄

io.type(file) 检测对象是否为可用的句柄

io.flush() 向文件写入缓冲中的数据

io.lines() 返回一个迭代函数,每次调用将获得文件中的一行内容

完全模式

同一时间处理多个文件

错误处理

assert 和 error

local function add(a,b)
    assert(type(a)=="number","a不是一个数字")
    assert(type(b)=="number","b不是一个数字")
    return a+b
end
add(10)

error(message [, level]) 终止正执行的函数,返回message作为错误信息

pcall xpcall debug

pcall 接收函数和参数,并执行,返回结果:有错误、无错误

(似乎是用于函数的测试)

xpcall 可以指向一个错误处理函数

if pcall(function_name, ...) then
   --没错
else
   --有错
end 

https://www.runoob.com/lua/lua-object-oriented.html


树莓派上使用lua

https://www.mobibrw.com/2018/14357

https://github.com/vsergeev/lua-periphery Linux Peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) with Lua


在网上下载了一个Lua5.4中文版,它支持中文关键词

它修改的关键词不太符合我的语法,做了一些修改:

llex.c 常见关键字

其它的关键字,可以搜索源代码中的 static const luaL_Reg