猿问

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

我正在尝试使用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 这里


Smart猫小萌
浏览 230回答 2
2回答

青春有我

我没有用过 go,但看起来你从来没有Book为你创建的新书设置元表。我相当确定这不会自动发生。查看我在此处找到的示例https://github.com/stevedonovan/luar/blob/master/luar.go#L52这里重要的是,当创建用户数据或任何对象(您的书)时,您需要获取全局元表,然后将其设置为元表 L.SetMetaTable(-2)

茅侃侃

在 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")我希望有人会觉得它有用。完整代码在这里。
随时随地看视频慕课网APP

相关分类

Go
我要回答