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) }
// 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 }
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 }
// lua_rawset func (L *State) RawSet(index int) { C.lua_rawset(L.s, C.int(index)) }
// Similar to Settable, but does a raw assignment (i.e., without // metamethods). func (this *State) Rawset(index int) { C.lua_rawset(this.luastate, C.int(index)) }
// Similar to Settable, but does a raw assignment (i.e., without // metamethods). func (s *State) Rawset(index int) { C.lua_rawset(s.l, C.int(index)) }
func Rawset(s *State, index int) { C.lua_rawset((*C.lua_State)(s), C.int(index)) }