Lua代码嵌入Golang
Go版本:1.19
首先是Go语言直接调用Lua程序,并打印,把环境跑通
1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import lua "github.com/yuin/gopher-lua"
func main () {
L := lua . NewState ()
defer L . Close ()
// go
err := L . DoString ( `print("go go go!")` )
if err != nil {
return
}
}
Lua的stdout可以直接转到go的stdout里,不过只调用打印一下没用意义,最重要的是函数调用
Go调用Lua的函数
Go调用Lua的函数最常用,Lua程序里定义函数和数据的处理方式,Go通过HTTP或者TCP获取到数据后,调用Lua的函数对数据处理,处理后,结果返回到Go语言,写入数据库或进行其他处理。
1
2
3
function add ( a , b )
return a + b
end
Lua支持多个参数和多个返回值,参数好办,用lua.LNumber(123)
类型有:
LTNil
LTBool
LTNumber
LTString
LTFunction
LTUserData
LTThread
LTTable
LTChannel
返回值个数也可以是多个,调用CallByParam的时候,NRet就是返回参数个数,Fn是要调用的全局函数名,Protect为true时,如果没找到函数或者出错不会panic,只会返回err。
调用完成后,要以压栈的方式,一个一个取回返回值ret := L.Get(-1)
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
package main
import (
"fmt"
lua "github.com/yuin/gopher-lua"
)
func main () {
L := lua . NewState ()
defer L . Close ()
// go
err := L . DoFile ( "main.lua" )
if err != nil {
fmt . Print ( err . Error ())
return
}
err = L . CallByParam ( lua . P {
Fn : L . GetGlobal ( "add" ),
NRet : 1 ,
Protect : true ,
}, lua . LNumber ( 1 ), lua . LNumber ( 2 ))
if err != nil {
fmt . Print ( err . Error ())
return
}
ret := L . Get ( - 1 )
// 如果是2个返回值, NRet改为2
// ret2 := L.Get(2)
// L.Pop(2)
L . Pop ( 1 )
res , ok := ret .( lua . LNumber )
if ok {
fmt . Println ( res )
}
}
Lua调用Go的函数
Lua调用Go语言的函数就没那么常用,因为虚拟机在Go语言程序里,需要传递数据直接通过Go的SetGlobal或函数调用就可以了。
不过仍然有一种应用场景需要Lua调用Go语言的函数,例如数据处理过程中,需要发送一个异步HTTP请求,或者把数据插入到MySQL或者Redis,就可以调用Go的HTTP请求函数或数据库处理函数。
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
package main
import (
"fmt"
lua "github.com/yuin/gopher-lua"
)
func Add ( L * lua . LState ) int {
// 获取参数
arg1 := L . ToInt ( 1 )
arg2 := L . ToInt ( 2 )
ret := arg1 + arg2
// 返回值
L . Push ( lua . LNumber ( ret ))
// 返回值的个数
return 1
}
func main () {
L := lua . NewState ()
defer L . Close ()
// 注册全局函数
L . SetGlobal ( "add" , L . NewFunction ( Add ))
// go
err := L . DoFile ( "main.lua" )
if err != nil {
fmt . Print ( err . Error ())
return
}
}
LuaTable转为GoStruct
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
package main
import (
"fmt"
"github.com/yuin/gluamapper"
lua "github.com/yuin/gopher-lua"
)
func main () {
type Role struct {
Name string
}
type Person struct {
Name string
Age int
WorkPlace string
Role [] * Role
}
L := lua . NewState ()
if err := L . DoString ( `
person = {
name = "Michel",
age = "31", -- weakly input
work_place = "San Jose",
role = {
{
name = "Administrator"
},
{
name = "Operator"
}
}
}
` ); err != nil {
panic ( err )
}
var person Person
if err := gluamapper . Map ( L . GetGlobal ( "person" ).( * lua . LTable ), & person ); err != nil {
panic ( err )
}
fmt . Printf ( "%s %d" , person . Name , person . Age )
}