From 701d73e4a47964ea40100ab2f329ef1dcc0a6f83 Mon Sep 17 00:00:00 2001 From: unwox Date: Mon, 17 Jun 2024 14:28:27 +0600 Subject: make it possible to push go functions onto the lua stack --- lua.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------- main.go | 1 + worker.go | 12 +++++++++++- 3 files changed, 65 insertions(+), 11 deletions(-) diff --git a/lua.go b/lua.go index f13a8cb..199f13a 100644 --- a/lua.go +++ b/lua.go @@ -6,12 +6,24 @@ package main #include #include #include + +extern int luna_run_go_func(uintptr_t); + +static inline int luna_run(lua_State *l) { + return luna_run_go_func(lua_tonumber(l, lua_upvalueindex(1))); +} + +static inline void luna_push_function(lua_State *l, uintptr_t f) { + lua_pushinteger(l, f); + lua_pushcclosure(l, luna_run, 1); +} */ import "C" import ( "errors" - "unsafe" "log" + "runtime/cgo" + "unsafe" ) type LuaRef C.longlong @@ -19,6 +31,13 @@ type Lua struct { l *C.lua_State } +//export luna_run_go_func +func luna_run_go_func(f C.uintptr_t) C.int { + log.Println(f) + fn := cgo.Handle(f).Value().(func() int) + return C.int(fn()) +} + func (l *Lua) Start() { l.l = C.luaL_newstate() C.luaL_openlibs(l.l) @@ -89,8 +108,26 @@ func (l *Lua) PushString(str string) { C.lua_pushstring(l.l, cstr) } -func (l *Lua) PushTable(table map[string]string) { - C.lua_createtable(l.l, 0, C.int(len(table))) +// You may need to delete handle with .Delete() method later. +func (l *Lua) PushGoFunction(f func (l *Lua) int) cgo.Handle { + h := cgo.NewHandle(func () int { + return f(l) + }) + C.luna_push_function(l.l, C.uintptr_t(h)) + return h +} + +// CreateTable pushes a new table onto the stack. +func (l *Lua) CreateTable(len int) { + C.lua_createtable(l.l, 0, C.int(len)) +} +func (l *Lua) SetTableItem(key string) { + cstr := C.CString(key) + defer C.free(unsafe.Pointer(cstr)) + C.lua_setfield(l.l, -2, C.CString(key)) +} +func (l *Lua) PushStringTable(table map[string]string) { + l.CreateTable(len(table)) for k, v := range table { l.PushString(v) C.lua_setfield(l.l, -2, C.CString(k)) @@ -101,6 +138,13 @@ func (l *Lua) PushFromRef(ref LuaRef) { C.lua_rawgeti(l.l, C.LUA_REGISTRYINDEX, C.longlong(ref)); } +func (l *Lua) PushTableItem(key string) { + ckey := C.CString(key) + defer C.free(unsafe.Pointer(ckey)) + C.lua_pushstring(l.l, ckey); + C.lua_gettable(l.l, -2); +} + func (l *Lua) IsString(index int) bool { return C.lua_isstring(l.l, C.int(index)) == 1 } @@ -138,13 +182,6 @@ func (l *Lua) LoadString(code string) error { return nil } -func (l *Lua) PushTableItem(key string) { - ckey := C.CString(key) - defer C.free(unsafe.Pointer(ckey)) - C.lua_pushstring(l.l, ckey); - C.lua_gettable(l.l, -2); -} - func (l *Lua) RestoreStackFunc() func () { before := l.StackLen() return func () { @@ -162,3 +199,9 @@ func (l *Lua) RestoreStackFunc() func () { C.lua_settop(l.l, C.int(before)) } } + +func (l *Lua) SetGlobal(name string) { + cstr := C.CString(name) + defer C.free(unsafe.Pointer(cstr)) + C.lua_setglobal(l.l, cstr) +} diff --git a/main.go b/main.go index 6c993fb..793928d 100644 --- a/main.go +++ b/main.go @@ -55,6 +55,7 @@ func main() { go wrk.Listen() defer wrk.Stop() } + go func () { reader := bufio.NewReader(os.Stdin) for { diff --git a/worker.go b/worker.go index 2b563ef..646efea 100644 --- a/worker.go +++ b/worker.go @@ -85,7 +85,7 @@ func (w *Worker) Listen() { for k := range r.request.Header { fh[k] = r.request.Header.Get(k) } - w.lua.PushTable(fh) + w.lua.PushStringTable(fh) body, err := io.ReadAll(r.request.Body) if err != nil { @@ -173,6 +173,16 @@ func (w *Worker) Stop() { w.lua.Close() } +func (w *Worker) initLunaModule() { + w.lua.CreateTable(1) + w.lua.PushGoFunction(func (l *Lua) int { + l.PushString("Hello, " + l.ToString(-1)) + return 1 + }) + w.lua.SetTableItem("helloFromGo") + w.lua.SetGlobal("luna") +} + func (w *Worker) initRoutes() error { defer w.lua.RestoreStackFunc()() w.lua.PushFromRef(w.api) -- cgit v1.2.3