当前位置: 首页>>代码示例>>Golang>>正文
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))
}