// packDataValue packs the provided Go value into a C.DataValue for // shiping into C++ land. // // For simple types (bool, int, etc) value is converted into a // native C++ value. For anything else, including cases when value // has a type that has an underlying simple type, the Go value itself // is encapsulated into a C++ wrapper so that field access and method // calls work. // // This must be run from the main GUI thread due to the cases where // calling wrapGoValue is necessary. func packDataValue(value interface{}, dvalue *C.DataValue, engine *Engine, owner valueOwner) { datap := unsafe.Pointer(&dvalue.data) if value == nil { dvalue.dataType = C.DTInvalid return } switch value := value.(type) { case string: dvalue.dataType = C.DTString cstr, cstrlen := unsafeStringData(value) *(**C.char)(datap) = cstr dvalue.len = cstrlen case bool: dvalue.dataType = C.DTBool *(*bool)(datap) = value case int: if value > 1<<31-1 { dvalue.dataType = C.DTInt64 *(*int64)(datap) = int64(value) } else { dvalue.dataType = C.DTInt32 *(*int32)(datap) = int32(value) } case int64: dvalue.dataType = C.DTInt64 *(*int64)(datap) = value case int32: dvalue.dataType = C.DTInt32 *(*int32)(datap) = value case uint64: dvalue.dataType = C.DTUint64 *(*uint64)(datap) = value case uint32: dvalue.dataType = C.DTUint32 *(*uint32)(datap) = value case float64: dvalue.dataType = C.DTFloat64 *(*float64)(datap) = value case float32: dvalue.dataType = C.DTFloat32 *(*float32)(datap) = value case *Common: dvalue.dataType = C.DTObject *(*unsafe.Pointer)(datap) = value.addr case color.RGBA: dvalue.dataType = C.DTColor *(*uint32)(datap) = uint32(value.A)<<24 | uint32(value.R)<<16 | uint32(value.G)<<8 | uint32(value.B) default: dvalue.dataType = C.DTObject if obj, ok := value.(Object); ok { *(*unsafe.Pointer)(datap) = obj.Common().addr } else { *(*unsafe.Pointer)(datap) = wrapGoValue(engine, value, owner) } } }
// packDataValue packs the provided Go value into a C.DataValue for // shiping into C++ land. // // For simple types (bool, int, etc) value is converted into a // native C++ value. For anything else, including cases when value // has a type that has an underlying simple type, the Go value itself // is encapsulated into a C++ wrapper so that field access and method // calls work. // // This must be run from the main GUI thread due to the cases where // calling wrapGoValue is necessary. func packDataValue(value interface{}, dvalue *C.DataValue, engine *Engine, owner valueOwner) { datap := unsafe.Pointer(&dvalue.data) if value == nil { dvalue.dataType = C.DTInvalid return } switch value := value.(type) { case string: dvalue.dataType = C.DTString cstr, cstrlen := unsafeStringData(value) *(**C.char)(datap) = cstr dvalue.len = cstrlen case bool: dvalue.dataType = C.DTBool *(*bool)(datap) = value case int: dvalue.dataType = intDT *(*int)(datap) = value case int64: dvalue.dataType = C.DTInt64 *(*int64)(datap) = value case int32: dvalue.dataType = C.DTInt32 *(*int32)(datap) = value case float64: dvalue.dataType = C.DTFloat64 *(*float64)(datap) = value case float32: dvalue.dataType = C.DTFloat32 *(*float32)(datap) = value case *Object: dvalue.dataType = C.DTObject *(*unsafe.Pointer)(datap) = value.addr default: dvalue.dataType = C.DTObject *(*unsafe.Pointer)(datap) = wrapGoValue(engine, value, owner) } }
// packDataValue packs the provided Go value into a C.DataValue for // shiping into C++ land. // // For simple types (bool, int, etc) value is converted into a // native C++ value. For anything else, including cases when value // has a type that has an underlying simple type, the Go value itself // is encapsulated into a C++ wrapper so that field access and method // calls work. // // This must be run from the main GUI thread due to the cases where // calling wrapGoValue is necessary. func packDataValue(value interface{}, dvalue *C.DataValue, engine *Engine, owner valueOwner) { datap := unsafe.Pointer(&dvalue.data) if value == nil { dvalue.dataType = C.DTInvalid return } switch value := value.(type) { case string: dvalue.dataType = C.DTString cstr, cstrlen := unsafeStringData(value) *(**C.char)(datap) = cstr dvalue.len = cstrlen case bool: dvalue.dataType = C.DTBool *(*bool)(datap) = value case int: if value > 1<<31-1 { dvalue.dataType = C.DTInt64 *(*int64)(datap) = int64(value) } else { dvalue.dataType = C.DTInt32 *(*int32)(datap) = int32(value) } case int64: dvalue.dataType = C.DTInt64 *(*int64)(datap) = value case int32: dvalue.dataType = C.DTInt32 *(*int32)(datap) = value case uint64: dvalue.dataType = C.DTUint64 *(*uint64)(datap) = value case uint32: dvalue.dataType = C.DTUint32 *(*uint32)(datap) = value case float64: dvalue.dataType = C.DTFloat64 *(*float64)(datap) = value case float32: dvalue.dataType = C.DTFloat32 *(*float32)(datap) = value case *Common: dvalue.dataType = C.DTObject *(*unsafe.Pointer)(datap) = value.addr case color.RGBA: dvalue.dataType = C.DTColor *(*uint32)(datap) = uint32(value.A)<<24 | uint32(value.R)<<16 | uint32(value.G)<<8 | uint32(value.B) default: rv := reflect.ValueOf(value) switch rv.Type().Kind() { case reflect.Ptr: rv = rv.Elem() if rv.Kind() != reflect.Array && rv.Kind() != reflect.Slice { break } fallthrough case reflect.Array, reflect.Slice: dvalue.dataType = C.DTVariantList dataValues := make([]C.DataValue, rv.Len()) for i := range dataValues { packDataValue(rv.Index(i).Interface(), &dataValues[i], engine, owner) } switch len(dataValues) { case 0: *(*unsafe.Pointer)(unsafe.Pointer(&dvalue.data)) = C.newVariantList(nil, 0) default: *(*unsafe.Pointer)(unsafe.Pointer(&dvalue.data)) = C.newVariantList(&dataValues[0], C.int(len(dataValues))) } return } dvalue.dataType = C.DTObject if obj, ok := value.(Object); ok { *(*unsafe.Pointer)(datap) = obj.Common().addr } else { *(*unsafe.Pointer)(datap) = wrapGoValue(engine, value, owner) } } }