github.com/yuin/gopher-lua

基本使用

执行字符串

  1. L := lua.NewState()
  2. defer L.Close()
  3. if err := L.DoString(`print("hello")`); err != nil {
  4. panic(err)
  5. }

执行文件

  1. L := lua.NewState()
  2. defer L.Close()
  3. if err := L.DoFile("hello.lua"); err != nil {
  4. panic(err)
  5. }

数据类型

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中预定义类型进行比较

  1. lv := L.Get(-1) // get the value at the top of the stack
  2. if lv == lua.LTrue { // correct
  3. }
  4. if bl, ok := lv.(lua.LBool); ok && bool(bl) { // wrong
  5. }

lua调用golang

注册函数

  1. func Double(L *lua.LState) int {
  2. lv := L.ToInt(1) /* get argument */
  3. L.Push(lua.LNumber(lv * 2)) /* push result */
  4. return 1 /* number of results */
  5. }
  6. func main() {
  7. L := lua.NewState()
  8. defer L.Close()
  9. L.SetGlobal("num", lua.LNumber(2))
  10. L.SetGlobal("double", L.NewFunction(Double)) /* Original lua_setglobal uses stack... */
  11. if err := L.DoString(`print(double(num))`); err != nil {
  12. panic(err)
  13. }
  14. }

自定义模块

  1. func Loader(L *lua.LState) int {
  2. // register functions to the table
  3. mod := L.SetFuncs(L.NewTable(), exports)
  4. // register other stuff
  5. L.SetField(mod, "name", lua.LString("value"))
  6. L.Push(mod)
  7. return 1
  8. }
  9. var exports = map[string]lua.LGFunction{
  10. "myfunc": myfunc,
  11. }
  12. func myfunc(L *lua.LState) int {
  13. return 0
  14. }
  15. func main() {
  16. L := lua.NewState()
  17. defer L.Close()
  18. L.PreloadModule("mymodule", Loader)
  19. if err := L.DoString(`
  20. local m = require("mymodule")
  21. m.myfunc()
  22. print(m.name)`); err != nil {
  23. panic(err)
  24. }
  25. }

GO调用lua

  1. func main() {
  2. L := lua.NewState()
  3. defer L.Close()
  4. if err := L.DoFile("module.lua"); err != nil {
  5. panic(err)
  6. }
  7. if err := L.CallByParam(lua.P{
  8. Fn: L.GetGlobal("double"),
  9. NRet: 1,
  10. Protect: true,
  11. }, lua.LNumber(10)); err != nil {
  12. panic(err)
  13. }
  14. ret := L.Get(-1) // returned value
  15. fmt.Println(ret.String())
  16. L.Pop(1) // remove received value
  17. }
  18. module.lua
  19. function double(x)
  20. return x*2
  21. end


coroutines

  1. co, _ := L.NewThread() /* create a new thread */
  2. fn := L.GetGlobal("coro").(*lua.LFunction) /* get function from lua */
  3. for {
  4. st, err, values := L.Resume(co, fn)
  5. if st == lua.ResumeError {
  6. fmt.Println("yield break(error)")
  7. fmt.Println(err.Error())
  8. break
  9. }
  10. for i, lv := range values {
  11. fmt.Printf("%v : %v\n", i, lv)
  12. }
  13. if st == lua.ResumeOK {
  14. fmt.Println("yield break(ok)")
  15. break
  16. }
  17. }

context

  1. func main() {
  2. L := lua.NewState()
  3. defer L.Close()
  4. ctx, cancel := context.WithCancel(context.Background())
  5. L.SetContext(ctx)
  6. defer cancel()
  7. go func() {
  8. err := L.DoString(`
  9. i = 0
  10. while true
  11. do
  12. i = i + 1
  13. print(i)
  14. end`)
  15. if err!= nil {
  16. fmt.Println(err.Error())
  17. }
  18. }()
  19. cancel() // cancel the parent context
  20. }

提前编译

  1. // compiles it.
  2. func CompileLua(script string) (*lua.FunctionProto, error) {
  3. reader := strings.NewReader(script)
  4. chunk, err := parse.Parse(reader, filePath)
  5. if err != nil {
  6. return nil, err
  7. }
  8. proto, err := lua.Compile(chunk, filePath)
  9. if err != nil {
  10. return nil, err
  11. }
  12. return proto, nil
  13. }
  14. // DoCompiledFile takes a FunctionProto, as returned by CompileLua, and runs it in the LState. It is equivalent
  15. // to calling DoFile on the LState with the original source file.
  16. func DoCompiledFile(L *lua.LState, proto *lua.FunctionProto) error {
  17. lfunc := L.NewFunctionFromProto(proto)
  18. L.Push(lfunc)
  19. return L.PCall(0, lua.MultRet, nil)
  20. }
  21. // Example shows how to share the compiled byte code from a lua script between multiple VMs.
  22. func main() {
  23. codeToShare := CompileLua("mylua.lua")
  24. a := lua.NewState()
  25. b := lua.NewState()
  26. c := lua.NewState()
  27. DoCompiledFile(a, codeToShare)
  28. DoCompiledFile(b, codeToShare)
  29. DoCompiledFile(c, codeToShare)
  30. }

不支持的函数

  • string.dump
  • os.setlocale
  • lua_Debug.namewhat
  • package.loadlib
  • debug hooks