func main() { L := C.luaL_newstate() defer C.lua_close(L) C.luaL_openlibs(L) /* Load Lua libraries */ C.luaopen_cmsgpack(L) sumS := C.CString(sum) defer C.free(unsafe.Pointer(sumS)) C.luaL_loadstring(L, sumS) msg, _ := msgpack.Marshal([]int{1, 2, 3, 4, 5, 6}) C.lua_pushstring(L, cptr(msg)) dstr := C.CString("mpdata") defer C.free(unsafe.Pointer(dstr)) C.luaSetglobal(L, dstr) C.luaExecute(L) sum := C.lua_tonumber(L, -1) fmt.Println(sum) // Output: 21 }
func packLuaNumber(out io.Writer, state State, object int) (n int, err error) { value := float64(C.lua_tonumber(state.L, C.int(object))) i := int64(value) if float64(i) == value { return P.PackVarint(out, i) } return P.PackFloat64(out, value) }
// lua_tonumber func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumber(L.s, C.int(index))) }
// Converts the Lua value at the given valid index to a float64. The // Lua value must be a number or a string convertible to a number; otherwise, // Tonumber returns 0. func (this *State) Tonumber(index int) float64 { return float64(C.lua_tonumber(this.luastate, C.int(index))) }
//export golua_interface_newindex_callback func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr *C.char) int { L := Li.(*State) iface := L.registry[iid] ifacevalue := reflect.ValueOf(iface).Elem() field_name := C.GoString(field_name_cstr) fval := ifacevalue.FieldByName(field_name) if fval.Kind() == reflect.Ptr { fval = fval.Elem() } luatype := LuaValType(C.lua_type(L.s, 3)) switch fval.Kind() { case reflect.Bool: if luatype == LUA_TBOOLEAN { fval.SetBool(int(C.lua_toboolean(L.s, 3)) != 0) return 1 } else { L.PushString("Wrong assignment to field " + field_name) return -1 } case reflect.Int: fallthrough case reflect.Int8: fallthrough case reflect.Int16: fallthrough case reflect.Int32: fallthrough case reflect.Int64: if luatype == LUA_TNUMBER { fval.SetInt(int64(C.lua_tointeger(L.s, 3))) return 1 } else { L.PushString("Wrong assignment to field " + field_name) return -1 } case reflect.Uint: fallthrough case reflect.Uint8: fallthrough case reflect.Uint16: fallthrough case reflect.Uint32: fallthrough case reflect.Uint64: if luatype == LUA_TNUMBER { fval.SetUint(uint64(C.lua_tointeger(L.s, 3))) return 1 } else { L.PushString("Wrong assignment to field " + field_name) return -1 } case reflect.String: if luatype == LUA_TSTRING { fval.SetString(C.GoString(C.lua_tolstring(L.s, 3, nil))) return 1 } else { L.PushString("Wrong assignment to field " + field_name) return -1 } case reflect.Float32: fallthrough case reflect.Float64: if luatype == LUA_TNUMBER { fval.SetFloat(float64(C.lua_tonumber(L.s, 3))) return 1 } else { L.PushString("Wrong assignment to field " + field_name) return -1 } } L.PushString("Unsupported type of field " + field_name + ": " + fval.Type().String()) return -1 }
// Converts the Lua value at the given valid index to a float64. The // Lua value must be a number or a string convertible to a number; otherwise, // Tonumber returns 0. func (s *State) Tonumber(index int) float64 { return float64(C.lua_tonumber(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 }
func (state State) luaToGoValue(_lvalue int, outType *reflect.Type) (reflect.Value, error) { L := state.L lvalue := C.int(_lvalue) ltype := C.lua_type(L, lvalue) gkind := reflect.Invalid if outType != nil { gkind = (*outType).Kind() } switch ltype { case C.LUA_TNONE, C.LUA_TNIL: switch gkind { case reflect.Invalid, reflect.Func, reflect.Ptr, reflect.Interface: return reflect.ValueOf(nil), nil } case C.LUA_TBOOLEAN: switch gkind { case reflect.Invalid, reflect.Bool, reflect.Interface: cv := C.lua_toboolean(L, lvalue) var v bool if cv == 0 { v = false } else { v = true } return reflect.ValueOf(v), nil } //case C.LUA_TLIGHTUSERDATA: //case C.LUA_TTHREAD: case C.LUA_TNUMBER: switch gkind { case reflect.Int: v := int(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Int8: v := int8(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Int16: v := int16(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Int32: v := int32(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Int64: v := int64(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Uint: v := uint(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Uint8: v := uint8(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Uint16: v := uint16(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Uint32: v := uint32(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Uint64: v := uint64(C.lua_tointeger(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Float32: v := float32(C.lua_tonumber(L, lvalue)) return reflect.ValueOf(v), nil case reflect.Invalid, reflect.Interface, reflect.Float64: v := float64(C.lua_tonumber(L, lvalue)) return reflect.ValueOf(v), nil } case C.LUA_TSTRING: switch gkind { case reflect.Invalid, reflect.String, reflect.Interface: v := stringFromLua(L, lvalue) return reflect.ValueOf(v), nil } case C.LUA_TTABLE: if gkind == reflect.Slice && (*outType).Elem() == typeOfKeyValue { return state.luaTableToKeyValues(int(_lvalue)) } if gkind == reflect.Invalid || gkind == reflect.Interface || (outType != nil && *outType == reflect.TypeOf(theNullTable)) { tbl := state.NewLuaTable(int(lvalue)) return reflect.ValueOf(tbl), nil } case C.LUA_TFUNCTION: if gkind == reflect.Invalid || gkind == reflect.Interface || (outType != nil && *outType == reflect.TypeOf(theNullFunction)) { fn := state.NewLuaFunction(int(lvalue)) return reflect.ValueOf(fn), nil } case C.LUA_TUSERDATA: ref := C.clua_getGoRef(L, lvalue) if ref != nil { obj := (*refGo)(ref).obj objType := reflect.TypeOf(obj) objValue := reflect.ValueOf(obj) if gkind == reflect.Invalid || gkind == reflect.Interface { return objValue, nil } if outType != nil { if objType == *outType { return objValue, nil } if objType.Kind() == reflect.Ptr { if objType.Elem() == *outType { return objValue.Elem(), nil } } } } } return reflect.ValueOf(nil), fmt.Errorf("cannot convert from lua-type `%v' to go-type `%v'", luaTypeName(ltype), gkind) }
func (L *State) getNumber(i int) (ret float64) { return float64(C.lua_tonumber(L.s, C.int(i+1))) }
func Tonumber(s *State, index int) float64 { return float64( C.lua_tonumber((*C.lua_State)(s), C.int(index))) }