Files
vxcommon/lua/callback.go
T
2021-03-22 12:45:34 +03:00

74 lines
1.4 KiB
Go
Executable File

package lua
import (
"errors"
"sync"
"github.com/vxcontrol/golua/lua"
"github.com/vxcontrol/luar"
)
type luaCallback struct {
refTr int
refCb int
l *lua.State
mx *sync.Mutex
closed bool
}
func newLuaCallback(L *lua.State) *luaCallback {
if !L.IsFunction(-1) {
if !L.GetMetaField(-1, "__call") {
L.Pop(1)
return nil
}
// There leave the __call metamethod on stack.
L.Remove(-2)
}
l := L.NewThread()
refTr := L.Ref(lua.LUA_REGISTRYINDEX)
refCb := L.Ref(lua.LUA_REGISTRYINDEX)
return &luaCallback{l: l, refCb: refCb, refTr: refTr, mx: &sync.Mutex{}}
}
func (lc *luaCallback) Call(results interface{}, args ...interface{}) error {
lc.mx.Lock()
defer lc.mx.Unlock()
if lc.closed {
return errors.New("callback has already closed")
}
// Push the callable value.
lc.l.RawGeti(lua.LUA_REGISTRYINDEX, lc.refCb)
// Push the args.
for _, arg := range args {
luar.GoToLuaProxy(lc.l, arg)
}
if err := lc.l.Call(len(args), 1); err != nil {
lc.l.Pop(1)
return err
}
if err := luar.LuaToGo(lc.l, -1, results); err != nil {
}
lc.l.Pop(1)
return nil
}
func (lc *luaCallback) Close() {
lc.mx.Lock()
defer lc.mx.Unlock()
if !lc.closed {
lc.l.Unref(lua.LUA_REGISTRYINDEX, lc.refCb)
lc.l.Unref(lua.LUA_REGISTRYINDEX, lc.refTr)
lc.closed = true
}
}