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

Passing LTable to CallByParam #257

Closed
2 tasks done
Julien2313 opened this issue Dec 2, 2019 · 11 comments
Closed
2 tasks done

Passing LTable to CallByParam #257

Julien2313 opened this issue Dec 2, 2019 · 11 comments

Comments

@Julien2313
Copy link

Julien2313 commented Dec 2, 2019

  • GopherLua is a Lua5.1 implementation. You should be familiar with Lua programming language. Have you read Lua 5.1 reference manual carefully?
  • GopherLua is a Lua5.1 implementation. In Lua, to keep it simple, it is more important to remove functionalities rather than to add functionalities unlike other languages . If you are going to introduce some new cool functionalities into the GopherLua code base and the functionalities can be implemented by existing APIs, It should be implemented as a library.

Please answer the following before submitting your issue:

  1. What version of GopherLua are you using? :
    1cd887cd7036
  2. What version of Go are you using? :
    go version go1.13.3
  3. What operating system and processor architecture are you using? :
    linux/amd64
  4. What did you do? :
    Exactly like this issue :
    [Question][Help] How do I Passing a lua.LTable to a CallByParam #178
lTable.RawSetString("varTest", "test")
L.CallByParam(lua.P{
	[...],
}, &lTable)

When I print my lTable in Go, I get something like that :
{<nil> [] map[] map[varTest:test] [varTest] map[varTest:0]}

And in my test function in LUA :

function Test(tableTest)
	print("tableTest:", tableTest)
end

(I tried .Metatable() too, in case)

  1. What did you expect to see? :
    The keys and values in my lTable
  2. What did you see instead? :
    I get a nil
@epikur-io
Copy link

I tried to recreate you code and and hadn't any errors or unexpected behaviour.
I think the error in you code is the double reference &lTable just use lTable and it should work.

go.mod

module ltable

go 1.13

require github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036

main.go

package main

import (
	"fmt"

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

func main() {
	vm := lua.NewState(lua.Options{
		RegistrySize:     1024 * 20,
		RegistryMaxSize:  1024 * 80, 
		RegistryGrowStep: 32,      
	})
	ltbl := vm.NewTable()
	ltbl.RawSetString("varTest", lua.LString("Test!"))
	vm.DoString(`
	 function Test(tableTest)
		print("tableTest:", tableTest["varTest"])
	 end
	`)

	err := vm.CallByParam(lua.P{
		Protect: true,
		NRet:    0,
		Fn:      vm.GetGlobal("Test"),
	}, ltbl)

	if err != nil {
		fmt.Println(err)
		return
	}
}

@Julien2313
Copy link
Author

Julien2313 commented Dec 10, 2019

I still don't understand why my code isn't working, but yours is... Thanks for your help anyway, I'll dig deeper !

@Julien2313
Copy link
Author

Julien2313 commented Dec 10, 2019

Ok, my problem is because I use Handler instead of Fn. But, In my case, I get a lua.LFunction, not the name of the function...

@Julien2313 Julien2313 reopened this Dec 10, 2019
@Julien2313
Copy link
Author

Julien2313 commented Dec 10, 2019

package testLua1

import (
	lua "github.com/yuin/gopher-lua"
)

func TestLua1() {
	L := lua.NewState(lua.Options{
		RegistrySize:     1024 * 20,
		RegistryMaxSize:  1024 * 80,
		RegistryGrowStep: 32,
	})

	ltbl := L.NewTable()
	ltbl.RawSetString("varTest", lua.LString("Test!"))

	ftest := func(L *lua.LState) int {
		funk := L.CheckFunction(1)

		L.CallByParam(lua.P{
			Fn:      L,
			NRet:    0,
			Protect: true,
			Handler: funk,
		}, ltbl)
		return 0
	}

	var test = map[string]lua.LGFunction{
		"testGo": ftest,
	}
	mod := L.RegisterModule("luaTest", test)
	L.Push(mod)

	L.DoString(`
	 function Test(tableTest)
		print("tableTest:", tableTest["varTest"])
	 end
	 luaTest.testGo(Test)
	`)

}

Output = tableTest: nil

I could use funk.String() and then, as you, GetGobal(), but what if a function is private ? ...

@epikur-io
Copy link

epikur-io commented Dec 10, 2019

@Julien2313 It's a bit hard to say why your code didn't work since you posted only some parts of it. My guess is, that the problem was that you passed the variable with an ampersand &lTable to the L.CallByParam method. lTable is already a reference and with the additional "&" you get a double reference - the address (like: 0x0041ff) value to the Pointer. Just try out printing:

fmt.Println(lTable) // Prints out the table
fmt.Println(&lTable) // Prints out the reference addrdess: 0x0041ff

You will get a different output.

For information about gopher-lua module just look at other modules. Maybe this code will help you: https://github.com/epikur-io/glua-email

To load the module f.e. "glua-email" you just say:

L.PreloadModule("email", email.Loader)

I think this would be the way to go if you want to develope modules for gopher lua.
Also you might have a look at the other modules that exist and look at their code.
Other Lua Modules

@Julien2313
Copy link
Author

Julien2313 commented Dec 11, 2019

Thanks for your help !

This is the test code, you juste have to call de function, or change it to main().
And no, my LTable wasn't a pointer (I didn't use NewTable() in my other code) Anyway, I tried both, and it doesn't work... :/

@Julien2313
Copy link
Author

I guess my problem is because I don't use well the parameter handler

@Julien2313
Copy link
Author

With the PreloadModule() :

package main

import (
	lua "github.com/yuin/gopher-lua"
)

func main() {
	L := lua.NewState(lua.Options{
		RegistrySize:     1024 * 20,
		RegistryMaxSize:  1024 * 80,
		RegistryGrowStep: 32,
	})
	defer L.Close()

	ltbl := L.NewTable()
	ltbl.RawSetString("varTest", lua.LString("Test!"))

	ftest := func(L *lua.LState) int {
		funk := L.CheckFunction(1)

		_ = L.CallByParam(lua.P{
			Fn:      L,
			NRet:    0,
			Protect: true,
			Handler: funk,
		}, ltbl)
		return 0
	}
	L.PreloadModule("luaTest", ftest)

	if err := L.DoString(`
	 function Test(tableTest)
		print("yho")
		print("tableTest:", tableTest["varTest"])
	 end
	 luaTest(Test)
	`); err != nil {
		panic(err)
	}
}

Output :

panic: <string>:6: attempt to call a non-function object
	stack traceback:
	<string>:6: in main chunk
	[G]: ?

@epikur-io
Copy link

epikur-io commented Dec 13, 2019

I see there is an error I over looked:

L.CallByParam(lua.P{
			Fn:      L,
			NRet:    0,
			Protect: true,
			Handler: funk,
		}, ltbl)

"Fn" Should be the the lua function not the VM (L) itself. Also you don't need to set the "Handler" for L.CallByParam, just leave it blank.
Also the way you use "L.PreloadModule" is wrong.
I suggest you look again at the working example I provided above.

Edit: If you don't get your code working you can also contact me.
Mail: 3p1kur@protonmail.ch

@Julien2313
Copy link
Author

Julien2313 commented Dec 13, 2019

Ok, I tried a different way, and this is working pretty well :

package main

import (
	lua "github.com/yuin/gopher-lua"
)

func main() {
	L := lua.NewState(lua.Options{
		RegistrySize:     1024 * 20,
		RegistryMaxSize:  1024 * 80,
		RegistryGrowStep: 32,
	})
	defer L.Close()

	ltbl := L.NewTable()
	ltbl.RawSetString("varTest", lua.LString("Test!"))

	ftest := func(L *lua.LState) int {
		funk := L.CheckAny(1)

		if err := L.CallByParam(lua.P{
			Fn:   funk,
			NRet: 0,
			Protect: true,
		}, ltbl); err != nil {
			panic(err)
		}
		return 0
	}

	var test = map[string]lua.LGFunction{
		"testGo": ftest,
	}

	mod := L.RegisterModule("luaTest", test)
	L.Push(mod)

	if err := L.DoString(`
	 function Test(tableTest)
		print("tableTest:", tableTest["varTest"])
	 end
	 luaTest.testGo(Test)
	`); err != nil {
		panic(err)
	}
}

I don't know if I use in a bad way funk := L.CheckAny(1), but this is not really intuitive... Mostly when L.CheckFunction() exists and there is a field Handler *LFunction...

Thanks for your time @epikur-io !

@Julien2313
Copy link
Author

Ok, if I just change CheckAny to CheckFunction, it's working too.

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

No branches or pull requests

2 participants