zoukankan      html  css  js  c++  java
  • Golang中使用lua进行扩展

    前言

    最近在项目中需要使用lua进行扩展,发现github上有一个用golang编写的lua虚拟机,名字叫做gopher-lua.使用后发现还不错,借此分享给大家.

    数据类型

    lua中的数据类型与golang中的数据类型对应关系作者已经在文档中说明,值得注意的是类型是以L开头的,类型的名称是以LT开头的.
    golang中的数据转换为lua中的数据就必须转换为L开头的类型:

    str := "hello"
    num := 10
    L.LString(str)
    L.LNumber(float64(num))

    lua中的数据转换为golang中的数据,项目提供了ToInt,CheckString之类的函数来进行转换,但是这都是必须提前知道类型的,如果不知道就必须进行类型判断:

    value := L.Get(1)
    switch value.Type() {
    case lua.LTString:
    case lua.LTTable:
    ....
    }

    这里还可以使用gopher-luar来方便的进行类型转换.

    golang和lua互相调用函数

    golang中的函数必须转换为func(L *lua.State) int这种形式才能注入lua中,返回参数的int代表了返回参数的个数.

    func hello(L *lua.State) int {
         //将返回参数压入栈中
         L.Push(lua.LString("hello"))
         //返回参数为1个
         return 1
    }
    //注入lua中
    L.SetGlobal("hello", L.NewFunction(hello))

    在golang中调用lua函数,lua脚本中需先定义这个函数,然后调用CallByParam进行调用:

    //先获取lua中定义的函数
    fn := L.GetGlobal("hello")
    if err := L.CallByParam(lua.P{
        Fn: fn,
        NRet: 1,
        Protect: true,
        }, lua.LNumber(10)); err != nil {
        panic(err)
    }
    //这里获取函数返回值
    ret := L.Get(-1)

    Table

    关于lua中的table是一个很强大的东西,项目对table也提供了很多方法的支持比如获取一个字段,添加一个字段.这里推荐使用gluamapper,可以将tabl转换为golang中的结构体或者map[string]interface{}类型,这里使用了作者提供的例子:

    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)

    模块的加载与使用

    项目中提供了lua基本模块,调用OpenLibs就可以加载这些模块,其中包括io,math,os,debug等.如果想自己加载可以使用SkipOpenLibs参数跳过.
    如果想开发自己的库,文档中也做出了说明:

    func Loader(L *lua.LState) int {
        //注册模块中的导出函数
        mod := L.SetFuncs(L.NewTable(), exports)
        L.Push(mod)
        return 1
    }
    
    var exports = map[string]lua.LGFunction{
        "myfunc": myfunc,
    }
    
    func myfunc(L *lua.LState) int {
        return 0
    }
    //这里就可以加载mymodule模块
    L.PreloadModule("mymodule", mymodule.Loader)
  • 相关阅读:
    希望走过的路成为未来的基石
    第三次个人作业--用例图设计
    第二次结对作业
    第一次结对作业
    第二次个人编程作业
    第一次个人编程作业(更新至2020.02.07)
    Springboot vue 前后分离 跨域 Activiti6 工作流 集成代码生成器 shiro权限
    springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
    spring cloud springboot 框架源码 activiti工作流 前后分离 集成代码生成器
    java代码生成器 快速开发平台 二次开发 外包项目利器 springmvc SSM后台框架源码
  • 原文地址:https://www.cnblogs.com/zhangboyu/p/7686209.html
Copyright © 2011-2022 走看看