func TypeNeedsWrapper(ti *gi.TypeInfo) bool { switch tag := ti.Tag(); tag { case gi.TYPE_TAG_VOID: if ti.IsPointer() { return false } panic("Non-pointer void type is not supported") case gi.TYPE_TAG_UTF8, gi.TYPE_TAG_FILENAME, gi.TYPE_TAG_GLIST, gi.TYPE_TAG_GSLIST, gi.TYPE_TAG_GHASH: return true case gi.TYPE_TAG_ARRAY: size := ti.ArrayFixedSize() if size != -1 { return TypeNeedsWrapper(ti.ParamType(0)) } return true case gi.TYPE_TAG_ERROR: panic("not implemented") case gi.TYPE_TAG_INTERFACE: switch ti.Interface().Type() { case gi.INFO_TYPE_CALLBACK, gi.INFO_TYPE_ENUM, gi.INFO_TYPE_FLAGS, gi.INFO_TYPE_STRUCT, gi.INFO_TYPE_UNION: return false } return true } return false }
func SimpleCgoType(ti *gi.TypeInfo, flags TypeFlags) string { tag := ti.Tag() switch tag { case gi.TYPE_TAG_VOID: if ti.IsPointer() { return "unsafe.Pointer" } panic("Non-pointer void type is not supported") case gi.TYPE_TAG_INTERFACE: bi := ti.Interface() switch bi.Type() { case gi.INFO_TYPE_ENUM, gi.INFO_TYPE_FLAGS: ei := gi.ToEnumInfo(bi) return GoTypeForTag(ei.StorageType(), flags|TypeExact) case gi.INFO_TYPE_STRUCT: ns := bi.Namespace() nm := bi.Name() fullnm := strings.ToLower(ns) + "." + nm if _, ok := GConfig.Sys.DisguisedTypes[fullnm]; ok { return "unsafe.Pointer" } } } if !strings.HasPrefix(CgoType(ti, flags), "*") { return GoTypeForTag(tag, flags|TypeExact) } return "unsafe.Pointer" }
func simple_cgo_type(ti *gi.TypeInfo, flags type_flags) string { tag := ti.Tag() switch tag { case gi.TYPE_TAG_VOID: if ti.IsPointer() { return "unsafe.Pointer" } panic("Non-pointer void type is not supported") case gi.TYPE_TAG_INTERFACE: bi := ti.Interface() switch bi.Type() { case gi.INFO_TYPE_ENUM, gi.INFO_TYPE_FLAGS: ei := gi.ToEnumInfo(bi) return go_type_for_tag(ei.StorageType(), flags|type_exact) case gi.INFO_TYPE_STRUCT: ns := bi.Namespace() nm := bi.Name() fullnm := strings.ToLower(ns) + "." + nm if config.is_disguised(fullnm) { return "unsafe.Pointer" } } } if !strings.HasPrefix(cgo_type(ti, flags), "*") { return go_type_for_tag(tag, flags|type_exact) } return "unsafe.Pointer" }
func GoToCgo(ti *gi.TypeInfo, arg0, arg1 string, flags ConvFlags) string { var out bytes.Buffer printf := PrinterTo(&out) switch tag := ti.Tag(); tag { case gi.TYPE_TAG_VOID: if ti.IsPointer() { printf("%s = unsafe.Pointer(%s)", arg1, arg0) break } printf("<ERROR: void>") case gi.TYPE_TAG_UTF8, gi.TYPE_TAG_FILENAME: printf("%s = _GoStringToGString(%s)", arg1, arg0) if flags&ConvOwnEverything == 0 { printf("\ndefer C.free(unsafe.Pointer(%s))", arg1) } case gi.TYPE_TAG_ARRAY: switch ti.ArrayType() { case gi.ARRAY_TYPE_C: var nelem string if ti.IsZeroTerminated() { nelem = fmt.Sprintf("(len(%s) + 1)", arg0) } else { nelem = fmt.Sprintf("len(%s)", arg0) } // alloc memory printf("%s = (%s)(C.malloc(C.size_t(int(unsafe.Sizeof(*%s)) * %s)))\n", arg1, CgoType(ti, TypeNone), arg1, nelem) printf("defer C.free(unsafe.Pointer(%s))\n", arg1) // convert elements printf("for i, e := range %s {\n", arg0) array := CgoArrayToGoArray(ti.ParamType(0), arg1) conv := GoToCgo(ti.ParamType(0), "e", array+"[i]", flags) printf(PrintLinesWithIndent(conv)) printf("}") // write a trailing zero if necessary (TODO: buggy) if ti.IsZeroTerminated() { printf("\n%s[len(%s)] = nil", array, arg0) } } case gi.TYPE_TAG_GLIST: case gi.TYPE_TAG_GSLIST: case gi.TYPE_TAG_GHASH: case gi.TYPE_TAG_ERROR: case gi.TYPE_TAG_INTERFACE: if ti.IsPointer() { flags |= ConvPointer } printf(GoToCgoForInterface(ti.Interface(), arg0, arg1, flags)) default: if ti.IsPointer() { flags |= ConvPointer } printf(GoToCgoForTag(tag, arg0, arg1, flags)) } return out.String() }
func CgoToGo(ti *gi.TypeInfo, arg1, arg2 string, flags ConvFlags) string { var out bytes.Buffer printf := PrinterTo(&out) switch tag := ti.Tag(); tag { case gi.TYPE_TAG_VOID: if ti.IsPointer() { printf("%s = %s", arg2, arg1) break } printf("<ERROR: void>") case gi.TYPE_TAG_UTF8, gi.TYPE_TAG_FILENAME: printf("%s = C.GoString(%s)", arg2, arg1) if flags&ConvOwnEverything != 0 { printf("\nC.g_free(unsafe.Pointer(%s))", arg1) } case gi.TYPE_TAG_ARRAY: switch ti.ArrayType() { case gi.ARRAY_TYPE_C: // array was allocated already at this point printf("for i := range %s {\n", arg2) array := CgoArrayToGoArray(ti.ParamType(0), arg1) conv := CgoToGo(ti.ParamType(0), array+"[i]", arg2+"[i]", flags) printf(PrintLinesWithIndent(conv)) printf("}") } case gi.TYPE_TAG_GLIST: ptype := ti.ParamType(0) printf("for iter := (*_GList)(unsafe.Pointer(%s)); iter != nil; iter = iter.next {\n", arg1) elt := fmt.Sprintf("(%s)(iter.data)", ForcePointer(CgoType(ptype, TypeReturn|TypeListMember))) printf("\tvar elt %s\n", GoType(ptype, TypeReturn|TypeListMember)) conv := CgoToGo(ptype, elt, "elt", flags|ConvListMember) printf(PrintLinesWithIndent(conv)) printf("\t%s = append(%s, elt)\n", arg2, arg2) printf("}") case gi.TYPE_TAG_GSLIST: ptype := ti.ParamType(0) printf("for iter := (*_GSList)(unsafe.Pointer(%s)); iter != nil; iter = iter.next {\n", arg1) elt := fmt.Sprintf("(%s)(iter.data)", ForcePointer(CgoType(ptype, TypeReturn|TypeListMember))) printf("\tvar elt %s\n", GoType(ptype, TypeReturn|TypeListMember)) conv := CgoToGo(ptype, elt, "elt", flags|ConvListMember) printf(PrintLinesWithIndent(conv)) printf("\t%s = append(%s, elt)\n", arg2, arg2) printf("}") case gi.TYPE_TAG_GHASH: case gi.TYPE_TAG_ERROR: printf("if %s != nil {\n", arg1) printf("\t%s = errors.New(C.GoString(((*_GError)(unsafe.Pointer(%s))).message))\n", arg2, arg1) printf("\tC.g_error_free(%s)\n", arg1) printf("}\n") case gi.TYPE_TAG_INTERFACE: if ti.IsPointer() { flags |= ConvPointer } printf(CgoToGoForInterface(ti.Interface(), arg1, arg2, flags)) default: if ti.IsPointer() { flags |= ConvPointer } printf(CgoToGoForTag(tag, arg1, arg2, flags)) } return out.String() }
// returns the size of a type, works only for TypeExact func TypeSize(ti *gi.TypeInfo, flags TypeFlags) int { ptrsize := int(unsafe.Sizeof(unsafe.Pointer(nil))) switch tag := ti.Tag(); tag { case gi.TYPE_TAG_VOID: if ti.IsPointer() { return ptrsize } panic("Non-pointer void type is not supported") case gi.TYPE_TAG_UTF8, gi.TYPE_TAG_FILENAME, gi.TYPE_TAG_GLIST, gi.TYPE_TAG_GSLIST, gi.TYPE_TAG_GHASH: return ptrsize case gi.TYPE_TAG_ARRAY: size := ti.ArrayFixedSize() if size != -1 { return size * TypeSize(ti.ParamType(0), flags) } return ptrsize case gi.TYPE_TAG_INTERFACE: if ti.IsPointer() { flags |= TypePointer } return TypeSizeForInterface(ti.Interface(), flags) default: if ti.IsPointer() { flags |= TypePointer } return TypeSizeForTag(tag, flags) } panic("unreachable: " + ti.Tag().String()) }
func CgoType(ti *gi.TypeInfo, flags TypeFlags) string { var out bytes.Buffer switch tag := ti.Tag(); tag { case gi.TYPE_TAG_VOID: if ti.IsPointer() { out.WriteString("unsafe.Pointer") break } panic("Non-pointer void type is not supported in cgo") case gi.TYPE_TAG_UTF8, gi.TYPE_TAG_FILENAME: out.WriteString("*C.char") case gi.TYPE_TAG_ARRAY: switch ti.ArrayType() { case gi.ARRAY_TYPE_C: out.WriteString("*") out.WriteString(CgoType(ti.ParamType(0), flags)) case gi.ARRAY_TYPE_ARRAY: out.WriteString("*C.GArray") case gi.ARRAY_TYPE_PTR_ARRAY: out.WriteString("*C.GPtrArray") case gi.ARRAY_TYPE_BYTE_ARRAY: out.WriteString("*C.GByteArray") } case gi.TYPE_TAG_GLIST: out.WriteString("*C.GList") case gi.TYPE_TAG_GSLIST: out.WriteString("*C.GSList") case gi.TYPE_TAG_GHASH: out.WriteString("*C.GHashTable") case gi.TYPE_TAG_ERROR: out.WriteString("*C.GError") case gi.TYPE_TAG_INTERFACE: if ti.IsPointer() { flags |= TypePointer } out.WriteString(CgoTypeForInterface(ti.Interface(), flags)) default: if ti.IsPointer() { out.WriteString("*") } out.WriteString(CgoTypeForTag(tag, flags)) } return out.String() }
func GoType(ti *gi.TypeInfo, flags TypeFlags) string { var out bytes.Buffer switch tag := ti.Tag(); tag { case gi.TYPE_TAG_VOID: if ti.IsPointer() { out.WriteString("unsafe.Pointer") break } panic("Non-pointer void type is not supported") case gi.TYPE_TAG_UTF8, gi.TYPE_TAG_FILENAME: if flags&TypeExact != 0 { out.WriteString("unsafe.Pointer") } else { out.WriteString("string") } case gi.TYPE_TAG_ARRAY: size := ti.ArrayFixedSize() if size != -1 { fmt.Fprintf(&out, "[%d]", size) } else { if flags&TypeExact != 0 { out.WriteString("unsafe.Pointer") } else { out.WriteString("[]") } } out.WriteString(GoType(ti.ParamType(0), flags)) case gi.TYPE_TAG_GLIST: if flags&TypeExact != 0 { out.WriteString("unsafe.Pointer") } else { out.WriteString("[]") out.WriteString(GoType(ti.ParamType(0), flags|TypeListMember)) } case gi.TYPE_TAG_GSLIST: if flags&TypeExact != 0 { out.WriteString("unsafe.Pointer") } else { out.WriteString("[]") out.WriteString(GoType(ti.ParamType(0), flags|TypeListMember)) } case gi.TYPE_TAG_GHASH: if flags&TypeExact != 0 { out.WriteString("unsafe.Pointer") } else { out.WriteString("map[") out.WriteString(GoType(ti.ParamType(0), flags)) out.WriteString("]") out.WriteString(GoType(ti.ParamType(1), flags)) } case gi.TYPE_TAG_ERROR: // not used? out.WriteString("error") case gi.TYPE_TAG_INTERFACE: if ti.IsPointer() { flags |= TypePointer } out.WriteString(GoTypeForInterface(ti.Interface(), flags)) default: if ti.IsPointer() { flags |= TypePointer } out.WriteString(GoTypeForTag(tag, flags)) } return out.String() }
func CType(ti *gi.TypeInfo, flags TypeFlags) string { var out bytes.Buffer switch tag := ti.Tag(); tag { case gi.TYPE_TAG_VOID: if ti.IsPointer() { out.WriteString("void*") break } out.WriteString("void") case gi.TYPE_TAG_UTF8, gi.TYPE_TAG_FILENAME: out.WriteString("char*") case gi.TYPE_TAG_ARRAY: switch ti.ArrayType() { case gi.ARRAY_TYPE_C: out.WriteString(CType(ti.ParamType(0), flags)) out.WriteString("*") case gi.ARRAY_TYPE_ARRAY: out.WriteString("GArray*") case gi.ARRAY_TYPE_PTR_ARRAY: out.WriteString("GPtrArray*") case gi.ARRAY_TYPE_BYTE_ARRAY: out.WriteString("GByteArray*") } case gi.TYPE_TAG_GLIST: out.WriteString("GList*") case gi.TYPE_TAG_GSLIST: out.WriteString("GSList*") case gi.TYPE_TAG_GHASH: out.WriteString("GHashTable*") case gi.TYPE_TAG_ERROR: out.WriteString("GError*") case gi.TYPE_TAG_INTERFACE: if ti.IsPointer() { flags |= TypePointer } out.WriteString(CTypeForInterface(ti.Interface(), flags)) default: out.WriteString(CTypeForTag(tag, flags)) if ti.IsPointer() { out.WriteString("*") } } return out.String() }