Skip to content

Commit

Permalink
module
Browse files Browse the repository at this point in the history
  • Loading branch information
vlorc committed Dec 13, 2018
1 parent eaeefa7 commit 3ea5975
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 5 deletions.
2 changes: 1 addition & 1 deletion base/bit.go
Expand Up @@ -27,5 +27,5 @@ func (BitFactory) Not(v uint64) uint64 {
}

func (BitFactory) Test(v, r uint64) bool {
return 0 != (v >> r)&1
return 0 != (v>>r)&1
}
6 changes: 3 additions & 3 deletions base/tobuffer.go
Expand Up @@ -54,11 +54,11 @@ func __newBufferN(L *lua.LState) Buffer {
func __newBuffer1(v lua.LValue) Buffer {
switch v.Type() {
case lua.LTString:
__stringBuffer(string(v.(lua.LString)))
return __stringBuffer(string(v.(lua.LString)))
case lua.LTNumber:
__allocBuffer(int(v.(lua.LNumber)), 0)
return __allocBuffer(int(v.(lua.LNumber)), 0)
case lua.LTUserData:
__dataBuffer(v.(*lua.LUserData).Value)
return __dataBuffer(v.(*lua.LUserData).Value)
}
return nil
}
Expand Down
11 changes: 11 additions & 0 deletions demo/module.lua
@@ -0,0 +1,11 @@
local M = {}

function M:hello(s)
print("hello:",s)
end

function M:add(a,b)
return a + b
end

return M
2 changes: 2 additions & 0 deletions go.mod
@@ -1,6 +1,8 @@
module github.com/vlorc/lua-vm

require (
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7
github.com/yuin/gopher-lua v0.0.0-20180827083657-b942cacc89fe
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd
golang.org/x/text v0.3.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
@@ -1,3 +1,7 @@
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 h1:noHsffKZsNfU38DwcXWEPldrTjIZ8FPNKx8mYMGnqjs=
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7/go.mod h1:bbMEM6aU1WDF1ErA5YJ0p91652pGv140gGw4Ww3RGp8=
github.com/yuin/gopher-lua v0.0.0-20180827083657-b942cacc89fe h1:5Zfs+TirasJUUDUjrHEdMW6XoFmfQxpuPS58cJgoZBQ=
github.com/yuin/gopher-lua v0.0.0-20180827083657-b942cacc89fe/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
Expand Down
7 changes: 6 additions & 1 deletion main/main.go
Expand Up @@ -48,10 +48,15 @@ func main() {
)

now := time.Now()
err := p.DoFile("demo/buffer.lua")
module, err := p.ModuleFile("demo/module.lua")
if nil != err {
println("error: ", err.Error())
}

var add func(int, int) int
module.Method("add", &add)
println("add:", add(1, 2))

last := time.Now()
println("time: ", (last.UnixNano()-now.UnixNano())/1000000, last.Unix()-now.Unix())
}
100 changes: 100 additions & 0 deletions pool/module.go
@@ -0,0 +1,100 @@
package pool

import (
"github.com/yuin/gopher-lua"
"layeh.com/gopher-luar"
"reflect"
"sync"
)

type module struct {
state *lua.LState
table *lua.LTable
method sync.Map
}

func (m *module) To(val interface{}, name ...string) bool {
if len(name) > 0 {
return __toValue(m.state.GetField(m.table, name[0]), val)
}
return __toValue(m.table, val)
}

func (m *module) Call(name string, args ...interface{}) {
m.__callByName(name, 0, nil, args...)
}

func (m *module) Method(name string, val interface{}) bool {
method := m.__method(name)
if nil == method {
return false
}
typ := reflect.TypeOf(val).Elem()
build := func(*lua.LState) []reflect.Value {
return nil
}
if typ.NumOut() > 0 {
build = func(state *lua.LState) []reflect.Value {
result := make([]reflect.Value, typ.NumOut())
top := state.GetTop()
for i, l := 0, typ.NumOut(); i < l; i++ {
v := reflect.New(typ.Out(i))
result[i] = v.Elem()
if i < top {
__toValue(state.Get(-(i + 1)), v.Interface())
}
}
return result
}
}
reflect.ValueOf(val).Elem().Set(
reflect.MakeFunc(
typ,
func(args []reflect.Value) (results []reflect.Value) {
var params []interface{}
if len(args) > 0 {
params = make([]interface{}, len(args))
for i := range args {
if args[i].IsValid() {
params[i] = args[i].Interface()
}
}
}
return m.__call(method, typ.NumOut(), build, params...)
}),
)
return true
}

func (m *module) __method(name string) (method *lua.LFunction) {
if it, ok := m.method.Load(name); ok {
method = it.(*lua.LFunction)
} else if f := m.state.GetField(m.table, name); lua.LTFunction == f.Type() {
method = f.(*lua.LFunction)
m.method.Store(name, method)
}
return
}

func (m *module) __callByName(name string, nret int, result func(*lua.LState) []reflect.Value, args ...interface{}) []reflect.Value {
return m.__call(m.__method(name), nret, result, args...)
}

func (m *module) __call(method *lua.LFunction, nret int, result func(*lua.LState) []reflect.Value, args ...interface{}) []reflect.Value {
thread, cancelFunc := m.state.NewThread()
defer thread.Close()
if cancelFunc != nil {
defer cancelFunc()
}
defer thread.SetTop(0)
thread.Push(method)
thread.Push(m.table)
for _, v := range args {
thread.Push(luar.New(thread, v))
}
thread.Call(len(args)+1, nret)
if nil != result {
return result(thread)
}
return nil
}
24 changes: 24 additions & 0 deletions pool/pool.go
Expand Up @@ -63,3 +63,27 @@ func (p *LuaPool) Preload(load ...func(*lua.LState) error) *LuaPool {
p.init = append(p.init, load...)
return p
}

func (p *LuaPool) ModuleString(source string) (LuaModule, error) {
L := p.Get()
if err := L.DoString(source); nil != err {
return nil, err
}
return __toModule(L), nil
}

func (p *LuaPool) ModuleFile(file string) (LuaModule, error) {
L := p.Get()
if err := L.DoFile(file); nil != err {
return nil, err
}
return __toModule(L), nil
}

func __toModule(state *lua.LState) LuaModule {
table := state.ToTable(-1)
return &module{
state: state,
table: table,
}
}
7 changes: 7 additions & 0 deletions pool/types.go
@@ -0,0 +1,7 @@
package pool

type LuaModule interface {
To(val interface{}, name ...string) bool
Call(name string, args ...interface{})
Method(name string, val interface{}) bool
}

0 comments on commit 3ea5975

Please sign in to comment.