Lua代码嵌入Golang

Go版本:1.19
首先是Go语言直接调用Lua程序,并打印,把环境跑通

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语言,写入数据库或进行其他处理。

  • Lua代码
    在这里插入图片描述
function add(a,b)
    return a+b
end

Lua支持多个参数和多个返回值,参数好办,用lua.LNumber(123)

类型有:

  • LTNil
  • LTBool
  • LTNumber
  • LTString
  • LTFunction
  • LTUserData
  • LTThread
  • LTTable
  • LTChannel

返回值个数也可以是多个,调用CallByParam的时候,NRet就是返回参数个数,Fn是要调用的全局函数名,Protecttrue时,如果没找到函数或者出错不会panic,只会返回err。

调用完成后,要以压栈的方式,一个一个取回返回值ret := L.Get(-1)

  • Go代码
    在这里插入图片描述
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请求函数或数据库处理函数。

  • Lua
print(add(10,20))
  • Go
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

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)
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐