mirror of
https://github.com/vxcontrol/vxcommon.git
synced 2026-07-21 04:25:27 -04:00
74 lines
1.4 KiB
Go
Executable File
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
|
|
}
|
|
}
|