为了账号安全,请及时绑定邮箱和手机立即绑定

golua - 使用定义的方法声明 lua 类

golua - 使用定义的方法声明 lua 类

Go
Smart猫小萌 2021-12-07 10:52:11
我正在尝试使用golua 包为我用 Go 编写的应用程序构建扩展 API。我的想法是让几个类暴露给 lua VM,例如Book类:local book = Book.Create("Le Petit Prince")print(book)book:save()我现在能做的只是基本的:type Book struct {    Id int64    Title string}func BookCreate(L *lua.State) int {    title := L.ToString(1)    p := &Book{Id: 1, Title: title}    L.PushGoStruct(p)    return 1}func BookToString(L *lua.State) int {    book, _ := L.ToGoStruct(1).(*Book)    L.PushString(fmt.Sprintf("Book(Id=%d, Title=\"%s\")", book.Id, book.Title))    return 1}L := lua.NewState()defer L.Close()L.OpenLibs()L.NewMetaTable("Book")L.SetMetaMethod("Create", BookCreate)L.SetMetaMethod("tostring", BookToString)L.SetGlobal("Book")这让我可以这样做:local book = Book.Create("Le Petit Prince")print(Book.tostring(book))但不是这个:local book = Book.Create("Le Petit Prince")print(book:tostring())// reflect: call of reflect.Value.Type on zero Value我的问题如何创建相当于声明 Lua 类的简化方法中描述的lua 类?如何将“魔法方法”添加到类像__tostring 这里
查看完整描述

2 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

我没有用过 go,但看起来你从来没有Book为你创建的新书设置元表。我相当确定这不会自动发生。

查看我在此处找到的示例https://github.com/stevedonovan/luar/blob/master/luar.go#L52

这里重要的是,当创建用户数据或任何对象(您的书)时,您需要获取全局元表,然后将其设置为元表 L.SetMetaTable(-2)


查看完整回答
反对 回复 2021-12-07
?
茅侃侃

TA贡献1842条经验 获得超21个赞

在 Lua中编程的C 中的用户定义类型我想出了可行的解决方案。我对 Lua 一无所知,对 Go 知之甚少,所以我的结论可能是错误的。


此版本的Lua 编程是为 Lua 5.0 编写的 - golua使用 Lua 5.1(目前)。


BookCreate 功能

我们创建新的用户数据,而不是推平转到结构到堆栈。然后我们将新创建的元表设置book为“Book”。


L.NewUserdata返回unsafe.Pointer所以我们将它转换为Book.


func BookCreate(L *lua.State) int {

    title := L.ToString(1)

    book := (*Book)(L.NewUserdata(uintptr(unsafe.Sizeof(Book{}))))


    L.LGetMetaTable("Book")

    L.SetMetaTable(-2)


    book.Id = 1;

    book.Title = title;


    return 1

}

BookToString 功能

在这里,我们只是把用户数据从堆栈,将其转换为Book。


请注意,我们从堆栈中弹出的内容可能不是指向Bookstruct 的指针,因此如果我们想防止 nil 指针/其他 Go 错误,可能需要进行一些基本的类型检查。


func BookToString(L *lua.State) int {

    book := (*Book)(L.ToUserdata(1))

    L.PushString(fmt.Sprintf("Book(Id=%d, Title=\"%s\")", book.Id, book.Title))


    return 1

}

main 功能

我们初始化新的“Book”元表并使自己成为自己的元表。我们增加了两个方法Create,并__tostring做出“尚书”一个全球性的。


L := lua.NewState()

defer L.Close()

L.OpenLibs()


L.NewMetaTable("Book")

L.PushString("__index")

L.PushValue(-2)

L.SetTable(-3)

L.SetMetaMethod("Create", BookCreate)

L.SetMetaMethod("__tostring", BookToString)

L.SetGlobal("Book")

这就是我们现在可以在 Lua 中做的事情:


local book = Book.Create('Le Petit Prince')

print(book)

print(book:__tostring())

print(Book.__tostring(book))


--out:

Book(Id=1, Title="Le Petit Prince")

Book(Id=1, Title="Le Petit Prince")

Book(Id=1, Title="Le Petit Prince")

我希望有人会觉得它有用。完整代码在这里。


查看完整回答
反对 回复 2021-12-07
  • 2 回答
  • 0 关注
  • 229 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信