summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunwox <me@unwox.com>2024-06-17 14:28:27 +0600
committerunwox <me@unwox.com>2024-06-18 10:31:00 +0600
commit701d73e4a47964ea40100ab2f329ef1dcc0a6f83 (patch)
tree5b82a1f56922c8dc3cc79a329ad6f21f65649b64
parentcae471d4bced5f7490cc18e86b50e51df64ddb7b (diff)
make it possible to push go functions onto the lua stack
-rw-r--r--lua.go63
-rw-r--r--main.go1
-rw-r--r--worker.go12
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 <lua.h>
#include <lualib.h>
#include <lauxlib.h>
+
+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)