github.com/yuin/gopher-lua
基本使用
执行字符串
L := lua.NewState()defer L.Close()if err := L.DoString(`print("hello")`); err != nil {panic(err)}
执行文件
L := lua.NewState()defer L.Close()if err := L.DoFile("hello.lua"); err != nil {panic(err)}
数据类型
| Type name | Go type | Type() value | Constants |
|---|---|---|---|
LNilType |
(constants) | LTNil |
LNil |
LBool |
(constants) | LTBool |
LTrue, LFalse |
LNumber |
float64 | LTNumber |
- |
LString |
string | LTString |
- |
LFunction |
struct pointer | LTFunction |
- |
LUserData |
struct pointer | LTUserData |
- |
LState |
struct pointer | LTThread |
- |
LTable |
struct pointer | LTTable |
- |
LChannel |
chan LValue | LTChannel |
- |
数据类型判断LNilType and LBool需要使用gopher-lua中预定义类型进行比较
lv := L.Get(-1) // get the value at the top of the stackif lv == lua.LTrue { // correct}if bl, ok := lv.(lua.LBool); ok && bool(bl) { // wrong}
lua调用golang
注册函数
func Double(L *lua.LState) int {lv := L.ToInt(1) /* get argument */L.Push(lua.LNumber(lv * 2)) /* push result */return 1 /* number of results */}func main() {L := lua.NewState()defer L.Close()L.SetGlobal("num", lua.LNumber(2))L.SetGlobal("double", L.NewFunction(Double)) /* Original lua_setglobal uses stack... */if err := L.DoString(`print(double(num))`); err != nil {panic(err)}}
自定义模块
func Loader(L *lua.LState) int {// register functions to the tablemod := L.SetFuncs(L.NewTable(), exports)// register other stuffL.SetField(mod, "name", lua.LString("value"))L.Push(mod)return 1}var exports = map[string]lua.LGFunction{"myfunc": myfunc,}func myfunc(L *lua.LState) int {return 0}func main() {L := lua.NewState()defer L.Close()L.PreloadModule("mymodule", Loader)if err := L.DoString(`local m = require("mymodule")m.myfunc()print(m.name)`); err != nil {panic(err)}}
GO调用lua
func main() {L := lua.NewState()defer L.Close()if err := L.DoFile("module.lua"); err != nil {panic(err)}if err := L.CallByParam(lua.P{Fn: L.GetGlobal("double"),NRet: 1,Protect: true,}, lua.LNumber(10)); err != nil {panic(err)}ret := L.Get(-1) // returned valuefmt.Println(ret.String())L.Pop(1) // remove received value}module.luafunction double(x)return x*2end
coroutines
co, _ := L.NewThread() /* create a new thread */fn := L.GetGlobal("coro").(*lua.LFunction) /* get function from lua */for {st, err, values := L.Resume(co, fn)if st == lua.ResumeError {fmt.Println("yield break(error)")fmt.Println(err.Error())break}for i, lv := range values {fmt.Printf("%v : %v\n", i, lv)}if st == lua.ResumeOK {fmt.Println("yield break(ok)")break}}
context
func main() {L := lua.NewState()defer L.Close()ctx, cancel := context.WithCancel(context.Background())L.SetContext(ctx)defer cancel()go func() {err := L.DoString(`i = 0while truedoi = i + 1print(i)end`)if err!= nil {fmt.Println(err.Error())}}()cancel() // cancel the parent context}
提前编译
// compiles it.func CompileLua(script string) (*lua.FunctionProto, error) {reader := strings.NewReader(script)chunk, err := parse.Parse(reader, filePath)if err != nil {return nil, err}proto, err := lua.Compile(chunk, filePath)if err != nil {return nil, err}return proto, nil}// DoCompiledFile takes a FunctionProto, as returned by CompileLua, and runs it in the LState. It is equivalent// to calling DoFile on the LState with the original source file.func DoCompiledFile(L *lua.LState, proto *lua.FunctionProto) error {lfunc := L.NewFunctionFromProto(proto)L.Push(lfunc)return L.PCall(0, lua.MultRet, nil)}// Example shows how to share the compiled byte code from a lua script between multiple VMs.func main() {codeToShare := CompileLua("mylua.lua")a := lua.NewState()b := lua.NewState()c := lua.NewState()DoCompiledFile(a, codeToShare)DoCompiledFile(b, codeToShare)DoCompiledFile(c, codeToShare)}
不支持的函数
string.dumpos.setlocalelua_Debug.namewhatpackage.loadlib- debug hooks
