예제 #1
0
파일: lgo.go 프로젝트: reusee/lgo
func (self *Lua) RegisterFunction(name string, fun interface{}) {
	path := strings.Split(name, ".")
	name = path[len(path)-1]
	path = path[0 : len(path)-1]
	if len(path) == 0 {
		path = append(path, "_G")
	}

	// ensure namespaces
	for i, namespace := range path {
		cNamespace := cstr(namespace)
		if i == 0 { // top namespace
			what := C.lua_getglobal(self.State, cNamespace)
			if what == C.LUA_TNIL { // not exists
				C.lua_settop(self.State, -2)
				C.lua_createtable(self.State, 0, 0)
				C.lua_setglobal(self.State, cNamespace)
				C.lua_getglobal(self.State, cNamespace)
			}
			if C.lua_type(self.State, -1) != C.LUA_TTABLE {
				self.Panic("global %s is not a table", namespace)
			}
		} else { // sub namespace
			C.lua_pushstring(self.State, cNamespace)
			C.lua_rawget(self.State, -2)
			if C.lua_type(self.State, -1) == C.LUA_TNIL {
				C.lua_settop(self.State, -2)
				C.lua_pushstring(self.State, cNamespace)
				C.lua_createtable(self.State, 0, 0)
				C.lua_rawset(self.State, -3)
				C.lua_pushstring(self.State, cNamespace)
				C.lua_rawget(self.State, -2)
			}
			if C.lua_type(self.State, -1) != C.LUA_TTABLE {
				self.Panic("namespace %s is not a table", namespace)
			}
		}
	}

	// register function
	funcType := reflect.TypeOf(fun)
	if funcType.IsVariadic() {
		self.Panic("cannot register variadic function: %v", fun)
	}
	argc := funcType.NumIn()
	cName := cstr(name)
	function := &Function{
		fun:       fun,
		lua:       self,
		name:      name,
		funcType:  funcType,
		funcValue: reflect.ValueOf(fun),
		argc:      argc,
	}
	funcId := rand.Int63()
	functionRegister.Set(funcId, function)
	C.register_function(self.State, cName, (C.int64_t)(funcId))
	self.Functions[name] = function
	C.lua_settop(self.State, -2)
}
예제 #2
0
파일: lobject.go 프로젝트: hxyxj/goinfi
func (tbl *Table) Foreach(fn func(key interface{}, value interface{}) bool) {
	if tbl.Ref == 0 {
		return
	}

	L := tbl.VM.globalL
	state := State{tbl.VM, L}
	bottom := C.lua_gettop(L)
	defer C.lua_settop(L, bottom)
	tbl.PushValue(state)

	ltable := C.lua_gettop(L)
	C.lua_pushnil(L)
	for {
		if 0 == C.lua_next(L, ltable) {
			return
		}

		vkey, err := state.luaToGoValue(-2, nil)
		if err != nil {
			return
		}
		vvalue, err := state.luaToGoValue(-1, nil)
		if err != nil {
			return
		}

		cont := fn(vkey.Interface(), vvalue.Interface())
		if !cont {
			return
		}

		C.lua_settop(L, -2)
	}
}
예제 #3
0
파일: pack.go 프로젝트: hxyxj/goinfi
func packLuaTable(out io.Writer, state State, object int, depth int) (n int, err error) {
	depth++
	L := state.L

	if depth > MAX_PACK_DEPTH {
		return 0, fmt.Errorf("pack too depth, depth=%v", depth)
	}

	n = 0
	err = nil
	var mapSize int = 0
	C.lua_pushnil(L)
	for {
		if 0 == C.lua_next(L, C.int(object)) {
			break
		}
		mapSize++
		C.lua_settop(L, -2) // pop 1
	}

	var ni int
	ni, err = P.PackMapHead(out, uint32(mapSize))
	n += ni
	if err != nil {
		return
	}

	C.lua_pushnil(L)
	for {
		if 0 == C.lua_next(L, C.int(object)) {
			break
		}

		top := int(C.lua_gettop(L))
		// key
		ni, err = packLuaObject(out, state, top-1, depth)
		n += ni
		if err != nil {
			C.lua_settop(L, -3) // pop 2
			return
		}
		// value
		ni, err = packLuaObject(out, state, top, depth)
		n += ni
		if err != nil {
			C.lua_settop(L, -3) // pop 2
			return
		}
		C.lua_settop(L, -2) // removes value, keeps key for next iteration
	}

	return
}
예제 #4
0
파일: gobject.go 프로젝트: hxyxj/goinfi
func (state *State) luaTableToKeyValues(ltable int) (value reflect.Value, err error) {
	var vvalue reflect.Value
	L := state.L

	size := sizeOfLuaTable(L, ltable)
	result := make([]base.KeyValue, 0, size)

	C.lua_pushnil(L)
	for {
		if 0 == C.lua_next(L, C.int(ltable)) {
			break
		}

		lvalue := int(C.lua_gettop(L))
		lkey := lvalue - 1

		vkey, err := state.luaToGoValue(lkey, nil)
		if err != nil {
			C.lua_settop(L, -3) // pop 2
			break
		}

		if C.LUA_TTABLE == C.lua_type(L, C.int(lvalue)) {
			vvalue, err = state.luaTableToKeyValues(lvalue)
		} else {
			vvalue, err = state.luaToGoValue(lvalue, nil)
		}
		if err != nil {
			C.lua_settop(L, -3) // pop 2
			break
		}

		key := vkey.Interface()
		var skey string
		if s, ok := key.(string); ok {
			skey = s
		} else {
			skey = fmt.Sprint(key)
		}
		value := vvalue.Interface()

		result = append(result, base.KeyValue{skey, value})

		C.lua_settop(L, -2) // pop 1
	}

	return reflect.ValueOf(result), err
}
예제 #5
0
파일: glua.go 프로젝트: gooops/glua
// 注册Go库到lua
func (L *State) Register(lib *Libfuncs) (bool, error) {
	libn := C.CString(lib.Libname)
	defer C.free(unsafe.Pointer(libn))

	// 获取GlibTable
	fsize := len(lib.Funcs)
	if C.GetGlibTable(L.s, libn, C.int(fsize)) != 0 {
		return false, errors.New(fmt.Sprintf("Lib name(%s) is wrong.\n", lib.Libname))
	}

	// 设置函数
	for k, v := range lib.Funcs {
		// 检查函数列表
		if ok, err := checkFuncInOutArgs(v); !ok {
			log.Println(err)
			continue
		}
		// 保存到State
		L.lf = append(L.lf, v)
		idx := len(L.lf)
		kn := C.CString(k)
		// 设置index到GlibTtable
		C.SetGfunc(L.s, kn, C.int(idx-1))
		C.free(unsafe.Pointer(kn))
	}

	C.lua_settop(L.s, 0)

	return true, nil
}
예제 #6
0
파일: glua.go 프로젝트: gooops/glua
// 调用lua中的函数,但是只能返回bool, float, string,以及其他go特殊类型,int型被转换为float返回。
func (L *State) Call(fname string, args ...interface{}) (out []interface{}, ok bool) {
	fn := C.CString(fname)
	defer C.free(unsafe.Pointer(fn))

	top := int(C.lua_gettop(L.s))

	if C.int(1) != C.FindFuncs(L.s, fn) {
		ok = false
		out = append(out, errors.New(fmt.Sprintf("not find the function(%s).\n", fname)))
		return
	}

	num := len(args)
	for _, arg := range args {
		argt := rf.TypeOf(arg)
		argv := rf.ValueOf(arg)
		L.pushValueByType(argt.Kind(), &argv)
	}

	C.lua_call(L.s, C.int(num), C.LUA_MULTRET)

	for i := top; i < int(C.lua_gettop(L.s)); i++ {
		ret := L.getValueByLuaType(i)
		if ret.IsValid() {
			out = append(out, ret.Interface())
		} else {
			out = append(out, nil)
		}
	}
	C.lua_settop(L.s, C.int(top))
	ok = true
	return
}
예제 #7
0
파일: lobject.go 프로젝트: hxyxj/goinfi
func (tbl *Table) GetWithError(key interface{}) (interface{}, error) {
	if tbl.Ref == 0 {
		return nil, fmt.Errorf("cannot get a released lua table")
	}
	L := tbl.VM.globalL
	state := State{tbl.VM, L}
	bottom := C.lua_gettop(L)
	defer C.lua_settop(L, bottom)

	tbl.PushValue(state)

	vkey := reflect.ValueOf(key)
	ok := state.goToLuaValue(vkey)
	if !ok {
		return nil, fmt.Errorf("invalid key type for lua type: %v", vkey.Kind())
	}
	C.lua_gettable(L, C.int(-2))
	vvalue, err := state.luaToGoValue(-1, nil)
	if err != nil {
		return nil, err
	}

	if vvalue.IsValid() {
		return vvalue.Interface(), nil
	}
	return nil, nil
}
예제 #8
0
파일: lua.go 프로젝트: reusee/lua
// Peval evaluates a piece of lua code. no panic when error occur.
func (l *Lua) Peval(code string, envs ...interface{}) (returns []interface{}, err error) {
	defer C.lua_settop(l.State, 0)
	C.push_errfunc(l.State)
	curTop := C.lua_gettop(l.State)
	// parse
	cCode := C.CString(code)
	defer C.free(unsafe.Pointer(cCode))
	if ret := C.luaL_loadstring(l.State, cCode); ret != 0 { // load error
		return nil, fmt.Errorf("LOAD ERROR: %s", C.GoString(C.lua_tolstring(l.State, -1, nil)))
	}
	// env
	if len(envs) > 0 {
		if len(envs)%2 != 0 {
			return nil, fmt.Errorf("number of arguments not match")
		}
		C.lua_createtable(l.State, 0, 0)
		for i := 0; i < len(envs); i += 2 {
			name, ok := envs[i].(string)
			if !ok {
				return nil, fmt.Errorf("name must be string, not %v", envs[i])
			}
			C.lua_pushstring(l.State, cstr(name))
			err := l.pushGoValue(envs[i+1], name)
			if err != nil {
				return nil, err
			}
			C.lua_rawset(l.State, -3)
		}
		// set env
		C.set_eval_env(l.State)
	}
	// call
	l.err = nil
	if ret := C.lua_pcall(l.State, 0, C.LUA_MULTRET, -2); ret != 0 {
		// error occured
		return nil, fmt.Errorf("CALL ERROR: %s", C.GoString(C.lua_tolstring(l.State, -1, nil)))
	} else if l.err != nil { // error raise by invokeGoFunc
		return nil, l.err
	} else {
		// return values
		nReturn := C.lua_gettop(l.State) - curTop
		returns = make([]interface{}, int(nReturn))
		for i := C.int(0); i < nReturn; i++ {
			value, err := l.toGoValue(-1-i, interfaceType)
			if err != nil {
				return nil, err
			}
			if value != nil {
				returns[int(nReturn-1-i)] = value.Interface()
			} else {
				returns[int(nReturn-1-i)] = nil
			}
		}
	}
	return
}
예제 #9
0
파일: lua.go 프로젝트: hxyxj/goinfi
func callLuaFuncUtil(state State, inv []reflect.Value, nout int) ([]interface{}, error) {
	L := state.L
	bottom := int(C.lua_gettop(L))

	var result []interface{}
	var nluaout C.int
	var nin C.int
	if nout >= 0 {
		nluaout = C.int(nout)
		result = make([]interface{}, 0, nout)
	} else {
		nluaout = C.LUA_MULTRET
		result = make([]interface{}, 0, 1)
	}
	if inv != nil {
		for _, iarg := range inv {
			state.goToLuaValue(iarg)
		}
		nin = C.int(len(inv))
	} else {
		nin = 0
	}
	ret := int(C.lua_pcall(L, nin, nluaout, 0))
	if ret != 0 {
		err := stringFromLua(L, -1)
		C.lua_settop(L, -2)
		return result, errors.New(err)
	}
	top := int(C.lua_gettop(L))
	for i := bottom; i <= top; i++ {
		value, _ := state.luaToGoValue(i, nil)
		if value.IsValid() {
			result = append(result, value.Interface())
		} else {
			result = append(result, nil)
		}
	}
	rnout := C.int(top + 1 - bottom)
	C.lua_settop(L, -rnout-1)
	return result, nil
}
예제 #10
0
파일: gobject.go 프로젝트: hxyxj/goinfi
func sizeOfLuaTable(L *C.lua_State, ltable int) int {
	var size int = 0
	C.lua_pushnil(L)
	for {
		if 0 == C.lua_next(L, C.int(ltable)) {
			break
		}
		size++
		C.lua_settop(L, -2) // pop 1
	}
	return size
}
예제 #11
0
파일: lobject.go 프로젝트: hxyxj/goinfi
func (tbl *Table) GetnWithError() (int, error) {
	if tbl.Ref == 0 {
		return 0, fmt.Errorf("cannot get lenght a released lua table")
	}
	L := tbl.VM.globalL
	state := State{tbl.VM, L}
	bottom := int(C.lua_gettop(L))
	defer C.lua_settop(L, C.int(bottom))

	tbl.PushValue(state)

	n := int(C.lua_objlen(L, C.int(-1)))
	return n, nil
}
예제 #12
0
파일: pack.go 프로젝트: hxyxj/goinfi
func PackLuaObjects(out io.Writer, state State, from int, to int) (ok bool, err error) {
	L := state.L
	top := C.lua_gettop(L)
	ok = true
	err = nil
	for object := from; object <= to; object++ {
		_, err = PackLuaObject(out, state, object)
		if err != nil {
			ok = false
			break
		}
	}
	C.lua_settop(L, top)
	return ok, err
}
예제 #13
0
파일: lua.go 프로젝트: hxyxj/goinfi
func luaGetSubTable(L *C.lua_State, table C.int, key string) (bool, error) {
	pushStringToLua(L, key)
	C.lua_gettable(L, table)
	ltype := C.lua_type(L, -1)
	if ltype == C.LUA_TNIL {
		C.lua_createtable(L, 0, 0)
		// table[key] = {}
		pushStringToLua(L, key)
		C.lua_pushvalue(L, -2)
		C.lua_settable(L, table)
	}
	ltype = C.lua_type(L, -1)
	if ltype != C.LUA_TTABLE {
		C.lua_settop(L, -2)
		return false, fmt.Errorf("field `%v` exist, and it is not a table", key)
	}
	return true, nil
}
예제 #14
0
파일: lua.go 프로젝트: reusee/lua
func (l *Lua) set(fullname string, v interface{}) error {
	// ensure name
	errMsg := C.ensure_name(l.State, C.CString(fullname))
	if errMsg != nil {
		return fmt.Errorf("%s: %s", errMsg, fullname)
	}

	// push value
	err := l.pushGoValue(v, fullname)
	if err != nil {
		return err
	}

	// set
	C.lua_rawset(l.State, -3)
	// clear stack
	C.lua_settop(l.State, 0)

	return nil
}
예제 #15
0
파일: lua.go 프로젝트: hxyxj/goinfi
func (vm *VM) EvalStringWithError(str string, arg ...interface{}) ([]interface{}, error) {
	L := vm.globalL
	state := State{vm, L}
	s, n := stringToC(str)
	bottom := C.lua_gettop(L)
	defer C.lua_settop(L, bottom)

	ret := int(C.luaL_loadbuffer(L, s, n, nil))
	if ret != 0 {
		err := stringFromLua(L, -1)
		return make([]interface{}, 0), errors.New(err)
	}

	nout := -1
	if len(arg) > 0 {
		if x, ok := arg[0].(int); ok {
			nout = x
		}
	}
	return callLuaFuncUtil(state, nil, nout)
}
예제 #16
0
// Decodes the result from a function into a Go object.
func (e *ExecutionEngine) decodeResult() (interface{}, error) {
	// Encode Lua object into msgpack.
	rc := C.mp_pack(e.state)
	if rc != 1 {
		return nil, errors.New("skyd.ExecutionEngine: Unable to msgpack decode Lua result")
	}
	sz := C.size_t(0)
	ptr := C.lua_tolstring(e.state, -1, (*C.size_t)(&sz))
	str := C.GoStringN(ptr, (C.int)(sz))
	C.lua_settop(e.state, -(1)-1) // lua_pop()

	// Decode msgpack into a Go object.
	var ret interface{}
	decoder := msgpack.NewDecoder(bytes.NewBufferString(str), nil)
	err := decoder.Decode(&ret)
	if err != nil {
		return nil, err
	}

	return ret, nil
}
예제 #17
0
파일: lobject.go 프로젝트: hxyxj/goinfi
func (tbl *Table) Set(key interface{}, value interface{}) (bool, error) {
	if tbl.Ref == 0 {
		return false, fmt.Errorf("cannot set a released lua table")
	}
	L := tbl.VM.globalL
	state := State{tbl.VM, L}
	bottom := C.lua_gettop(L)
	defer C.lua_settop(L, bottom)

	tbl.PushValue(state)

	vkey := reflect.ValueOf(key)
	ok := state.goToLuaValue(vkey)
	if !ok {
		return false, fmt.Errorf("invalid key type for lua type: %v", vkey.Kind())
	}
	state.goToLuaValue(reflect.ValueOf(value))
	C.lua_settable(L, C.int(-3))

	return true, nil
}
예제 #18
0
파일: lgo.go 프로젝트: reusee/lgo
func (self *Lua) RunString(code string) {
	defer func() {
		if r := recover(); r != nil {
			if self.PrintTraceback { //NOCOVER
				print("============ start lua traceback ============\n")
				self.RunString(`print(debug.traceback())`)
				print("============ end lua traceback ==============\n")
			}
			panic(r)
		}
	}()
	cCode := cstr(code)
	C.setup_message_handler(self.State)
	if ret := C.luaL_loadstring(self.State, cCode); ret != C.int(0) {
		self.Panic("%s", C.GoString(C.lua_tolstring(self.State, -1, nil)))
	}
	ret := C.lua_pcallk(self.State, 0, 0, C.lua_gettop(self.State)-C.int(1), 0, nil)
	if ret != C.int(0) {
		self.Panic("%s", C.GoString(C.lua_tolstring(self.State, -1, nil)))
	}
	C.lua_settop(self.State, 0)
}
예제 #19
0
파일: lua.go 프로젝트: hxyxj/goinfi
func (vm *VM) EvalBufferWithError(reader io.Reader, arg ...interface{}) ([]interface{}, error) {
	L := vm.globalL
	state := State{vm, L}
	context := loadBufferContext{
		reader: reader,
		buf:    make([]byte, READ_BUFFER_SIZE),
	}
	bottom := C.lua_gettop(L)
	defer C.lua_settop(L, bottom)

	ret := int(C.clua_loadProxy(L, unsafe.Pointer(&context)))
	if ret != 0 {
		err := stringFromLua(L, -1)
		return make([]interface{}, 0), errors.New(err)
	}
	nout := -1
	if len(arg) > 0 {
		if x, ok := arg[0].(int); ok {
			nout = x
		}
	}
	return callLuaFuncUtil(state, nil, nout)
}
예제 #20
0
파일: State.go 프로젝트: rdlaitila/leaf
// Accepts any valid index, or 0, and sets the stack top to this
// index. If the new top is larger than the old one, then the new elements
// are filled with nil. If index is 0, then all stack elements are removed.
func (this *State) Settop(index int) {
	C.lua_settop(this.luastate, C.int(index))
}
예제 #21
0
파일: lua.go 프로젝트: matthewtidd/golua
func (L *State) Pop(n int) {
	//C.lua_pop(L.s, C.int(n));
	C.lua_settop(L.s, C.int(-n-1))
}
예제 #22
0
파일: state.go 프로젝트: halturin/luajit
// Accepts any valid index, or 0, and sets the stack top to this
// index. If the new top is larger than the old one, then the new elements
// are filled with nil. If index is 0, then all stack elements are removed.
func (s *State) Settop(index int) {
	C.lua_settop(s.l, C.int(index))
}
예제 #23
0
파일: glua.go 프로젝트: gooops/glua
func (L *State) setFuncOut(ft rf.Type, out []rf.Value) {
	C.lua_settop(L.s, 0)
	for i, v := range out {
		L.pushValueByType(ft.Out(i).Kind(), &v)
	}
}
예제 #24
0
파일: lgo.go 프로젝트: reusee/lgo
func (lua *Lua) toGoValue(i C.int, paramType reflect.Type) (ret reflect.Value) {
	luaType := C.lua_type(lua.State, i)
	paramKind := paramType.Kind()
	switch paramKind {
	case reflect.Bool:
		if luaType != C.LUA_TBOOLEAN {
			lua.Panic("not a boolean")
		}
		ret = reflect.ValueOf(C.lua_toboolean(lua.State, i) == C.int(1))
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if luaType != C.LUA_TNUMBER {
			lua.Panic("not an integer")
		}
		ret = reflect.New(paramType).Elem()
		ret.SetInt(int64(C.lua_tointegerx(lua.State, i, nil)))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if luaType != C.LUA_TNUMBER {
			lua.Panic("not an unsigned")
		}
		ret = reflect.New(paramType).Elem()
		ret.SetUint(uint64(C.lua_tointegerx(lua.State, i, nil)))
	case reflect.Float32, reflect.Float64:
		if luaType != C.LUA_TNUMBER {
			lua.Panic("not a float")
		}
		ret = reflect.New(paramType).Elem()
		ret.SetFloat(float64(C.lua_tonumberx(lua.State, i, nil)))
	case reflect.Interface:
		switch luaType {
		case C.LUA_TNUMBER:
			ret = reflect.New(floatType).Elem()
			ret.SetFloat(float64(C.lua_tonumberx(lua.State, i, nil)))
		case C.LUA_TSTRING:
			ret = reflect.New(stringType).Elem()
			ret.SetString(C.GoString(C.lua_tolstring(lua.State, i, nil)))
		case C.LUA_TLIGHTUSERDATA:
			ret = reflect.ValueOf(C.lua_topointer(lua.State, i))
		case C.LUA_TBOOLEAN:
			ret = reflect.New(boolType).Elem()
			ret.SetBool(C.lua_toboolean(lua.State, i) == C.int(1))
		//TODO nil
		//TODO table
		default:
			lua.Panic("wrong interface argument: %v", paramKind)
		}
	case reflect.String:
		if luaType != C.LUA_TSTRING {
			lua.Panic("not a string")
		}
		ret = reflect.New(paramType).Elem()
		ret.SetString(C.GoString(C.lua_tolstring(lua.State, i, nil)))
	case reflect.Slice:
		switch luaType {
		case C.LUA_TSTRING:
			ret = reflect.New(paramType).Elem()
			cstr := C.lua_tolstring(lua.State, i, nil)
			ret.SetBytes(C.GoBytes(unsafe.Pointer(cstr), C.int(C.strlen(cstr))))
		case C.LUA_TTABLE:
			ret = reflect.MakeSlice(paramType, 0, 0)
			C.lua_pushnil(lua.State)
			elemType := paramType.Elem()
			for C.lua_next(lua.State, i) != 0 {
				ret = reflect.Append(ret, lua.toGoValue(-1, elemType))
				C.lua_settop(lua.State, -2)
			}
		default:
			lua.Panic("wrong slice argument")
		}
	case reflect.Ptr:
		if luaType != C.LUA_TLIGHTUSERDATA {
			lua.Panic("not a pointer")
		}
		pointer := C.lua_topointer(lua.State, i)
		ret = reflect.NewAt(paramType, unsafe.Pointer(&pointer)).Elem()
	case reflect.Map:
		if luaType != C.LUA_TTABLE {
			lua.Panic("not a map")
		}
		ret = reflect.MakeMap(paramType)
		C.lua_pushnil(lua.State)
		keyType := paramType.Key()
		elemType := paramType.Elem()
		for C.lua_next(lua.State, i) != 0 {
			ret.SetMapIndex(
				lua.toGoValue(-2, keyType),
				lua.toGoValue(-1, elemType))
			C.lua_settop(lua.State, -2)
		}
	case reflect.UnsafePointer:
		ret = reflect.ValueOf(C.lua_topointer(lua.State, i))
	//TODO complex64/128
	//TODO array
	//TODO chan
	//TODO func
	//TODO struct
	default:
		lua.Panic("unknown argument type %v", paramType)
	}
	return
}
예제 #25
0
파일: lua.go 프로젝트: reusee/lua
func (l *Lua) toGoValue(i C.int, paramType reflect.Type) (ret *reflect.Value, err error) {
	luaType := C.lua_type(l.State, i)
	paramKind := paramType.Kind()
	switch paramKind {
	case reflect.Bool:
		if luaType != C.LUA_TBOOLEAN {
			err = fmt.Errorf("not a boolean")
			return
		}
		v := reflect.ValueOf(C.lua_toboolean(l.State, i) == C.int(1))
		ret = &v
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if luaType != C.LUA_TNUMBER {
			err = fmt.Errorf("not an integer")
			return
		}
		v := reflect.New(paramType).Elem()
		v.SetInt(int64(C.lua_tointeger(l.State, i)))
		ret = &v
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if luaType != C.LUA_TNUMBER {
			err = fmt.Errorf("not a unsigned")
			return
		}
		v := reflect.New(paramType).Elem()
		v.SetUint(uint64(C.lua_tointeger(l.State, i)))
		ret = &v
	case reflect.Float32, reflect.Float64:
		if luaType != C.LUA_TNUMBER {
			err = fmt.Errorf("not a float")
			return
		}
		v := reflect.New(paramType).Elem()
		v.SetFloat(float64(C.lua_tonumber(l.State, i)))
		ret = &v
	case reflect.Interface:
		switch paramType {
		case interfaceType:
			switch luaType {
			case C.LUA_TNUMBER:
				v := reflect.New(floatType).Elem() // always return float64 for interface{}
				v.SetFloat(float64(C.lua_tonumber(l.State, i)))
				ret = &v
			case C.LUA_TSTRING:
				v := reflect.New(stringType).Elem()
				v.SetString(C.GoString(C.lua_tolstring(l.State, i, nil)))
				ret = &v
			case C.LUA_TLIGHTUSERDATA, C.LUA_TUSERDATA:
				v := reflect.ValueOf(C.lua_touserdata(l.State, i))
				ret = &v
			case C.LUA_TBOOLEAN:
				v := reflect.New(boolType).Elem()
				v.SetBool(C.lua_toboolean(l.State, i) == C.int(1))
				ret = &v
			case C.LUA_TNIL:
				ret = nil
			default:
				err = fmt.Errorf("unsupported type %s for interface{}", luaTypeName(luaType))
				return
			}
		default:
			err = fmt.Errorf("only interface{} is supported, no %v", paramType)
			return
		}
	case reflect.String:
		if luaType != C.LUA_TSTRING {
			err = fmt.Errorf("not a string")
			return
		}
		v := reflect.New(paramType).Elem()
		v.SetString(C.GoString(C.lua_tolstring(l.State, i, nil)))
		ret = &v
	case reflect.Slice:
		switch luaType {
		case C.LUA_TSTRING:
			v := reflect.New(paramType).Elem()
			cstr := C.lua_tolstring(l.State, i, nil)
			v.SetBytes(C.GoBytes(unsafe.Pointer(cstr), C.int(C.strlen(cstr))))
			ret = &v
		case C.LUA_TTABLE:
			v := reflect.MakeSlice(paramType, 0, 0)
			C.lua_pushnil(l.State)
			elemType := paramType.Elem()
			for C.lua_next(l.State, i) != 0 {
				elemValue, e := l.toGoValue(-1, elemType)
				if e != nil {
					err = e
					return
				}
				// there is no nil value in lua table so elemValue will never be nil
				v = reflect.Append(v, *elemValue)
				C.lua_settop(l.State, -2)
				ret = &v
			}
		default:
			err = fmt.Errorf("wrong slice argument")
			return
		}
	case reflect.Ptr:
		if luaType != C.LUA_TLIGHTUSERDATA {
			err = fmt.Errorf("not a pointer")
			return
		}
		p := C.lua_topointer(l.State, i)
		v := reflect.NewAt(paramType, unsafe.Pointer(&p)).Elem()
		ret = &v
	case reflect.Map:
		if luaType != C.LUA_TTABLE {
			err = fmt.Errorf("not a map")
			return
		}
		v := reflect.MakeMap(paramType)
		C.lua_pushnil(l.State)
		keyType := paramType.Key()
		elemType := paramType.Elem()
		for C.lua_next(l.State, i) != 0 {
			keyValue, e := l.toGoValue(-2, keyType)
			if e != nil {
				err = e
				return
			}
			// table has no nil key so keyValue will not be nil
			elemValue, e := l.toGoValue(-1, elemType)
			if e != nil {
				err = e
				return
			}
			// table has no nil value so elemValue will not be nil
			v.SetMapIndex(*keyValue, *elemValue)
			C.lua_settop(l.State, -2)
		}
		ret = &v
	case reflect.UnsafePointer:
		v := reflect.ValueOf(C.lua_topointer(l.State, i))
		ret = &v
	default:
		err = fmt.Errorf("unsupported toGoValue type %v", paramType)
		return
	}
	return
}
예제 #26
0
파일: lua.go 프로젝트: szll/golua
// lua_pop
func (L *State) Pop(n int) {
	//Why is this implemented this way? I don't get it...
	//C.lua_pop(L.s, C.int(n));
	C.lua_settop(L.s, C.int(-n-1))
}
예제 #27
0
파일: lua.go 프로젝트: szll/golua
// lua_settop
func (L *State) SetTop(index int) {
	C.lua_settop(L.s, C.int(index))
}
예제 #28
0
파일: core.go 프로젝트: vron/lua
func Pop(s *State, n int) {
	// Is defined as a macro, so we define it:
	C.lua_settop((*C.lua_State)(s), C.int(-n-1))
}