Exemple #1
0
// 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
}
Exemple #2
0
// Pcall calls a lua function. no panic
func (l *Lua) Pcall(fullname string, args ...interface{}) (returns []interface{}, err error) {
	C.push_errfunc(l.State)
	curTop := C.lua_gettop(l.State)
	// get function
	path := strings.Split(fullname, ".")
	for i, name := range path {
		if i == 0 {
			C.lua_getfield(l.State, C.LUA_GLOBALSINDEX, cstr(name))
		} else {
			if C.lua_type(l.State, -1) != C.LUA_TTABLE {
				return nil, fmt.Errorf("%s is not a function", fullname)
			}
			C.lua_pushstring(l.State, cstr(name))
			C.lua_gettable(l.State, -2)
			C.lua_remove(l.State, -2) // remove table
		}
	}
	if C.lua_type(l.State, -1) != C.LUA_TFUNCTION {
		return nil, fmt.Errorf("%s is not a function", fullname)
	}
	// args
	for _, arg := range args {
		l.pushGoValue(arg, "")
	}
	// call
	l.err = nil
	if ret := C.lua_pcall(l.State, C.int(len(args)), C.LUA_MULTRET, C.int(-(len(args))-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
			}
			returns[int(nReturn-1-i)] = value.Interface()
		}
	}
	return
}