func (lua *Lua) PushGoValue(value reflect.Value) { switch t := value.Type(); t.Kind() { case reflect.Bool: if value.Bool() { C.lua_pushboolean(lua.State, C.int(1)) } else { C.lua_pushboolean(lua.State, C.int(0)) } case reflect.String: C.lua_pushstring(lua.State, C.CString(value.String())) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: C.lua_pushnumber(lua.State, C.lua_Number(C.longlong(value.Int()))) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: C.lua_pushnumber(lua.State, C.lua_Number(C.ulonglong(value.Uint()))) case reflect.Float32, reflect.Float64: C.lua_pushnumber(lua.State, C.lua_Number(C.double(value.Float()))) case reflect.Slice: length := value.Len() C.lua_createtable(lua.State, C.int(length), 0) for i := 0; i < length; i++ { C.lua_pushnumber(lua.State, C.lua_Number(i+1)) lua.PushGoValue(value.Index(i)) C.lua_settable(lua.State, -3) } case reflect.Interface: lua.PushGoValue(value.Elem()) case reflect.Ptr, reflect.UnsafePointer: C.lua_pushlightuserdata(lua.State, unsafe.Pointer(value.Pointer())) default: lua.Panic("wrong return value %v %v", value, t.Kind()) } }
// Pushes a new Go closure onto the stack. // // When a Go function is created, it is possible to associate some // values with it, thus creating a Go closure; these values are then // accessible to the function whenever it is called. To associate values // with a Go function, first these values should be pushed onto the stack // (when there are multiple values, the first value is pushed first). Then // Pushclosure is called to create and push the Go function onto the // stack, with the argument n telling how many values should be associated // with the function. Pushclosure also pops these values from the stack. // // The maximum value for n is 254. func (this *State) Pushclosure(fn Gofunction, n int) { if !this.Checkstack(1) { panic("STATE: unable to grow lua_state stack") } C.lua_pushnumber(this.luastate, C.lua_Number(C.float(float64(this.gvindex)))) C.lua_pushnumber(this.luastate, C.lua_Number(C.float(float64(Gvregistry.AddValue(fn))))) C.goluajit_pushclosure(this.luastate, C.int(n+2)) }
// Pushes a new Go closure onto the stack. // // When a Go function is created, it is possible to associate some // values with it, thus creating a Go closure; these values are then // accessible to the function whenever it is called. To associate values // with a Go function, first these values should be pushed onto the stack // (when there are multiple values, the first value is pushed first). Then // Pushclosure is called to create and push the Go function onto the // stack, with the argument n telling how many values should be associated // with the function. Pushclosure also pops these values from the stack. // // The maximum value for n is 254. func (this *State) Pushclosure(fn lua.Function, n int) { if !this.Checkstack(1) { panic("STATE: unable to grow lua_state stack") } C.lua_pushnumber(this.luastate, C.lua_Number(C.float(float64(this.grindex)))) C.lua_pushnumber(this.luastate, C.lua_Number(C.float(float64(lua.GlobalRegistry.AddValue(fn))))) C.lua51_pushclosure(this.luastate, C.int(n+2)) }
func (state State) goToLuaValue(value reflect.Value) bool { L := state.L gkind := value.Kind() switch gkind { case reflect.Bool: v := value.Bool() if v { C.lua_pushboolean(L, 1) } else { C.lua_pushboolean(L, 0) } return true case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: v := value.Int() C.lua_pushinteger(L, C.lua_Integer(v)) return true case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: v := value.Uint() C.lua_pushinteger(L, C.lua_Integer(v)) return true // case reflect.Uintptr: case reflect.Float32, reflect.Float64: v := value.Float() C.lua_pushnumber(L, C.lua_Number(v)) return true // case reflect.Array: // case reflect.Complex64, reflect.Complex128: // case reflect.Chan // case reflect.Interface case reflect.Ptr: iv := value.Interface() if v, ok := iv.(ILuaRef); ok { v.PushValue(state) return true } state.pushObjToLua(value.Interface()) return true case reflect.Func, reflect.Map, reflect.Slice: state.pushObjToLua(value.Interface()) return true case reflect.String: v := value.String() pushStringToLua(L, v) return true case reflect.Struct: objPtr := reflect.New(value.Type()) objPtr.Elem().Set(value) state.pushObjToLua(objPtr.Interface()) return true //case reflect.UnsafePointer case reflect.Interface: return state.goToLuaValue(value.Elem()) } C.lua_pushnil(L) return false }
// luaL_optnumber func (L *State) OptNumber(narg int, d float64) float64 { return float64(C.luaL_optnumber(L.s, C.int(narg), C.lua_Number(d))) }
// lua_pushnumber func (L *State) PushNumber(n float64) { C.lua_pushnumber(L.s, C.lua_Number(n)) }
// Pushes a number with value n onto the stack. func (this *State) Pushnumber(n float64) { C.lua_pushnumber(this.luastate, C.lua_Number(n)) }
// Pushes a number with value n onto the stack. func (s *State) Pushnumber(n float64) { C.lua_pushnumber(s.l, C.lua_Number(n)) }
func (l *Lua) pushGoValue(v interface{}, name string) error { if v == nil { C.lua_pushnil(l.State) return nil } switch value := v.(type) { case bool: if value { C.lua_pushboolean(l.State, C.int(1)) } else { C.lua_pushboolean(l.State, C.int(0)) } case string: C.lua_pushstring(l.State, C.CString(value)) case int: C.lua_pushnumber(l.State, C.lua_Number(C.longlong(value))) case int8: C.lua_pushnumber(l.State, C.lua_Number(C.longlong(value))) case int16: C.lua_pushnumber(l.State, C.lua_Number(C.longlong(value))) case int32: C.lua_pushnumber(l.State, C.lua_Number(C.longlong(value))) case int64: C.lua_pushnumber(l.State, C.lua_Number(C.longlong(value))) case uint: C.lua_pushnumber(l.State, C.lua_Number(C.ulonglong(value))) case uint8: C.lua_pushnumber(l.State, C.lua_Number(C.ulonglong(value))) case uint16: C.lua_pushnumber(l.State, C.lua_Number(C.ulonglong(value))) case uint32: C.lua_pushnumber(l.State, C.lua_Number(C.ulonglong(value))) case uint64: C.lua_pushnumber(l.State, C.lua_Number(C.ulonglong(value))) case float32: C.lua_pushnumber(l.State, C.lua_Number(C.double(value))) case float64: C.lua_pushnumber(l.State, C.lua_Number(C.double(value))) case unsafe.Pointer: C.lua_pushlightuserdata(l.State, value) default: // not basic types, use reflect switch valueType := reflect.TypeOf(v); valueType.Kind() { case reflect.Func: // function if valueType.IsVariadic() { return fmt.Errorf("variadic function is not supported, %s", name) } function := &_Function{ name: name, lua: l, fun: v, funcType: valueType, funcValue: reflect.ValueOf(v), argc: valueType.NumIn(), } funcsLock.Lock() funcs = append(funcs, function) id := len(funcs) - 1 funcsLock.Unlock() C.push_go_func(l.State, C.int64_t(id)) case reflect.Slice: value := reflect.ValueOf(v) length := value.Len() C.lua_createtable(l.State, C.int(length), 0) for i := 0; i < length; i++ { C.lua_pushnumber(l.State, C.lua_Number(i+1)) err := l.pushGoValue(value.Index(i).Interface(), "") if err != nil { return err } C.lua_settable(l.State, -3) } case reflect.Ptr: C.lua_pushlightuserdata(l.State, unsafe.Pointer(reflect.ValueOf(v).Pointer())) default: // unknown type return fmt.Errorf("unsupported type %v", v) } } return nil }
func (L *State) pushNumber(f float64) { C.lua_pushnumber(L.s, C.lua_Number(f)) }
func Pushnumber(s *State, num float64) { C.lua_pushnumber((*C.lua_State)(s), C.lua_Number(num)) }