// lua_topointer func (L *State) ToPointer(index int) uintptr { return uintptr(C.lua_topointer(L.s, C.int(index))) }
// Converts the value at the given acceptable index to a uintptr. The // value can be a userdata, a table, a thread, or a function; otherwise, // Topointer returns nil. Different objects will give different // pointers. There is no way to convert the pointer back to its original // value. // // Typically this function is used only for debug information. func (this *State) Topointer(index int) unsafe.Pointer { return C.lua_topointer(this.luastate, C.int(index)) }
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 }
// Converts the value at the given acceptable index to a uintptr. The // value can be a userdata, a table, a thread, or a function; otherwise, // Topointer returns nil. Different objects will give different // pointers. There is no way to convert the pointer back to its original // value. // // Typically this function is used only for debug information. func (s *State) Topointer(index int) unsafe.Pointer { return C.lua_topointer(s.l, C.int(index)) }
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 }