Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert LUA types to go #34

Open
maja42 opened this issue Jun 17, 2022 · 6 comments
Open

Convert LUA types to go #34

maja42 opened this issue Jun 17, 2022 · 6 comments

Comments

@maja42
Copy link

maja42 commented Jun 17, 2022

gopher-luar is able to automatically convert lua-types into go - an example for that is given in the documentation.

However, this mechanism is not exposed in the API. While there is a luar.New(), the counterpart is missing.
This becomes necessary when calling lua-functions from go, and trying to get the function's return value:

// Convert from go-to-LUA
var args []interface{} = ...
lArgs := make([]lua.LValue, len(args))
for i, a := range args {
    lArgs[i] = luar.New(L, a)
}

var numberOfReturnArgs = 4
vm.state.CallByParam(lua.P{
    Fn:      L.GetGlobal("functionName"),
    NRet:    numberOfReturnArgs,
}, lArgs...)

// Collect return values:
retValues := make([]interface{}, returnArgs)
for i := returnArgs; i > 0; i-- {
    ret := vm.state.Get(-1)
    vm.state.Pop(1)

    retValues[i-1] = ret // <--- how to convert to go-type?
}

How can I convert these return-values to go-types?

@GwynethLlewelyn
Copy link

A good question! I was wondering the same... in my case, I just set another global, pass it to Lua, and let Lua fill it with the result. Clunky, I know, but it seems to work...

@vbargl
Copy link

vbargl commented Dec 5, 2023

For those who still does not know, all you need to do is register your go function through luar.
You can go little bit further and register whole module through luar:

func Preload(L *lua.LState) {
	L.PreloadModule("somemodule", Module)
}

func Module(L *lua.LState) int {
	api := luar.New(L, apiFuncs)
	L.Push(api)
	return 1
}

type MyType1 struct {
	Param1 string
}

var apiFuncs = map[string]any{
	"fun1": func(mt1 MyType1) string { ... },
	...
}

@maja42
Copy link
Author

maja42 commented Dec 6, 2023

I know this mechanism. I'm using it to call go functions from LUA.
But I'm asking for the opposite:
Calling LUA functions from go, and then converting the LUA return types back to go types.

@vbargl
Copy link

vbargl commented Dec 10, 2023

Okay, sorry I misunderstood. On the other hand this approach can be applied to little similar thing:

-- some lua file
local greeting = require('greeting')

local greetingForName = greeting.greet(
  function (name)
    return "Hello, " .. name .. "!\nfrom Lua"
  end
)

print(greetingForName .. " yay!")
// go module

package greeting

import (
	"fmt"

	lua "github.com/yuin/gopher-lua"
	luar "layeh.com/gopher-luar"
)

func Preload(L *lua.LState) {
	L.PreloadModule("greeting", Module)
}

func Module(L *lua.LState) int {
	api := luar.New(L, apiFuncs)
	L.Push(api)
	return 1
}

var apiFuncs = map[string]any{
	"greet": Greet,
}

func Greet(greeter func(string) string) string {
	return greeter("World")
}

I personally tested this and it works fine.
I don't know what is your flow but with this example you can map lua function to go function, run it and result pass back to lua.

@maja42
Copy link
Author

maja42 commented Dec 10, 2023

This is basically a workaround to access gopher-luar methods that already exist, but simply aren't exposed.

In my case, I solved the issue by using global variables that are exposed via modules. It's not perfect, but good enough for my use cases.
Still not as nice as simply exporting the existing functionality.

@maja42
Copy link
Author

maja42 commented Dec 10, 2023

In the end I stopped using gopher-luar all together. I'm now working with a custom fork of gopher-lua directly (contains a few bug fixes and some features regarding stdout/err/in handling) and do the type convertion myself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants