这一篇记录一些关于Lua的更深入一些的东西主要是table的使用。但是不涉及IO,Debug,垃圾回收,OOP,数据库访问。这些东西我觉得可以单独放在一个专题写。

lua调用其他平台库这里不做介绍

调用C库

包概念

环境配置

.bash_profile 文件中直接配置测试目录的路径,这样lua编译器会自动到这个目录寻找需要的文件。
这里是我用的目录Users/keyle/Desktop/LuaPlayground/?.lua
添加如下信息至 bash_profile 文件。

1
2
#LUA_PATH
export LUA_PATH="~/lua/?.lua;/Users/keyle/Desktop/LuaPlayground/?.lua;"

使用 source .bash_profile 命令使其生效

定义使用包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/local/bin/lua
complex = {} --包名需要与文件名同名
-- 私有函数
local function ptMethod(x)
print(x)
end
--实例函数
function complex.pt(content)
if content == nil then
ptMethod(complex.content)
else
print(content)
end
end
--实例变量
complex.content = "helloworld"
return complex

使用包

1
2
3
4
5
6
#!/usr/local/bin/lua
local c = require("complex") -- 使用require函数引入,我定义了一个局部变量 c 来接受这个包
c.pt() -- 调用别名为c的包内函数pt
c.pt("keyle")

元表

定义元表

方式一

1
2
3
table1 = {}
table1_meta = {}
setmetatable(table1,table1_meta)

方式二

1
setmetatable({},{})

使用元表查找

如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
setmetatable(table1,table1_meta)
table_test = setmetatable({0,1,"three",2},{
__index = function (table,key)
print(key .. "<<<<")
if key=="great" then
return "meta_table_t"
else
return table[key]
end
end
})
print(table_test.great)
print(table_test[2])
print(table_test[3])
--great<<<<
--meta_table_t
--1
--three

使用元表赋值

这里使用元表提供的函数提前拦截赋值的地方。然后使用rawset进行赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
table_test =setmetatable({},
{
__newindex = function(tb,key,value)
print(key .. " <-UPDATE-> " .. value)
rawset(tb,key,value)
end
})
table_test.key = "key1"
print(table_test.key)
-- 输出结果
-- key <-UPDATE-> key1
-- key1

元表运算符重载

可供重载的运算符列表

  • __add 对应的运算符 ‘+’.
  • __sub 对应的运算符 ‘-‘.
  • __mul 对应的运算符 ‘*’.
  • __div 对应的运算符 ‘/‘.
  • __mod 对应的运算符 ‘%’.
  • __unm 对应的运算符 ‘-‘.
  • __concat 对应的运算符 ‘..’.
  • __eq 对应的运算符 ‘==’.
  • __lt 对应的运算符 ‘<’.
  • __le 对应的运算符 ‘<=’.

重载了+运算符 ,其他的同理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
table_test =setmetatable({66,99,77},
{
__add = function(tb1,tb2)
for k,v in pairs(tb2) do
table.insert(tb1,k,v)
end
end
})
table3 = table_test+{33,44,11}
for k,v in pairs(table_test) do
print(k,v)
end

重载元表的 call 与 tostring

1
2
3
4
5
6
7
8
9
10
11
12
13
14
table_test =setmetatable({66,99,77},
{
__call = function(tb1,tb2)
for k,v in pairs(tb2) do
table.insert(tb1,k,v)
end
end
})
table_test({33,44,11})
for k,v in pairs(table_test) do
print(k,v)
end
1
2
3
4
5
6
7
8
9
10
11
table1 = setmetatable({33,44,11},{
__tostring = function(tb1)
total = 0
for k,v in pairs(tb1) do
total = total + v
end
return "value total >> " .. total .. "<<<"
end
})
print(table1)

coroutine 协程

Lua 协同程序(coroutine) - 来自 RUNOOB.COM

  • coroutine.create() 创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用
  • coroutine.resume() 重启coroutine,和create配合使用
  • coroutine.yield() 挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果
  • coroutine.status() 查看coroutine的状态
    注:coroutine的状态有三种:dead,suspend,running,具体什么时候有这样的状态请参考下面的程序
  • coroutine.wrap() 创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复
  • coroutine.running() 返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/local/bin/lua
-- coroutine_test.lua 文件
co = coroutine.create(
function(i)
print(i);
end
)
coroutine.resume(co, 1) -- 1
print(coroutine.status(co)) -- dead
print("----------")
co = coroutine.wrap(
function(i)
print(i);
end
)
co(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("----------")