Esempio n. 1
0
func (w *Writer) genTypeDef(d *cc.Decl) {
	w.writeDocString(d.Name, "")
	goName := cNameToGoUpper(d.Name)

	switch d.Type.Kind {
	case cc.Struct:
		if d.Type.Decls == nil || goName == "Path" {
			// Opaque typedef.
			w.Print(`type %s struct {
Ptr *C.%s
}`, goName, d.Name)

			cFinalizer := d.Name
			if strings.HasSuffix(cFinalizer, "_t") {
				cFinalizer = cFinalizer[:len(cFinalizer)-2]
			}
			cFinalizer += "_destroy"
			w.Print("func free%s(obj *%s) {", goName, goName)
			w.Print("C.%s(obj.Ptr)", cFinalizer)
			w.Print("}")

			w.Print("func wrap%s(p *C.%s) *%s {", goName, d.Name, goName)
			w.Print("ret := &%s{p}", goName)
			w.Print("runtime.SetFinalizer(ret, free%s)", goName)
			w.Print("return ret")
			w.Print("}")
		} else {
			sharedTypes[d.Name] = goName
			w.Print("type %s struct {", goName)
			for _, d := range d.Type.Decls {
				typ := cTypeToMap(d.Type)
				w.Print("%s %s", cNameToGoUpper(d.Name), typ.goType)
			}
			w.Print("}")
		}
	case cc.Enum:
		type constEntry struct {
			goName, cName string
		}
		consts := make([]constEntry, 0, len(d.Type.Decls))
		for _, d := range d.Type.Decls {
			constName := d.Name
			if strings.HasPrefix(constName, "CAIRO_") {
				constName = constName[len("CAIRO_"):]
			}
			constName = cNameToGoUpper(strings.ToLower(d.Name))
			consts = append(consts, constEntry{constName, d.Name})
		}

		w.Print("type %s int", goName)
		w.Print("const (")
		for _, c := range consts {
			w.Print("%s %s = C.%s", c.goName, goName, c.cName)
		}
		w.Print(")")

		if goName != "Status" {
			w.Print("func (i %s) String() string {", goName)
			w.Print("switch i {")
			for _, c := range consts {
				w.Print("case %s: return \"%s\"", c.goName, c.goName)
			}
			w.Print("default: return fmt.Sprintf(\"%s(%%d)\", i)", goName)
			w.Print("}")
			w.Print("}")
		}
	default:
		panic("unhandled decl " + d.String())
	}
}
Esempio n. 2
0
File: gen.go Progetto: evmar/gocairo
func (w *Writer) genTypeDef(d *cc.Decl) {
	w.writeDocString(d.Name, "")
	goName := cNameToGoUpper(d.Name)

	switch d.Type.Kind {
	case cc.Struct:
		if d.Type.Decls == nil || goName == "Path" {
			// Opaque typedef.
			w.Print(`type %s struct {
Ptr *C.%s
}`, goName, d.Name)

			cFinalizer := d.Name
			if strings.HasSuffix(cFinalizer, "_t") {
				cFinalizer = cFinalizer[:len(cFinalizer)-2]
			}
			cFinalizer += "_destroy"
			w.Print("func free%s(obj *%s) {", goName, goName)
			w.Print("C.%s(obj.Ptr)", cFinalizer)
			w.Print("}")

			w.Print("func wrap%s(p *C.%s) *%s {", goName, d.Name, goName)
			w.Print("ret := &%s{p}", goName)
			w.Print("runtime.SetFinalizer(ret, free%s)", goName)
			w.Print("return ret")
			w.Print("}")

			w.Print("// Wrap a C %s* found from some external source as a *%s.  The Go side will destroy the reference when it's no longer used.", d.Name, goName)
			w.Print("func Wrap%s(p unsafe.Pointer) *%s {", goName, goName)
			w.Print("return wrap%s((*C.%s)(p))", goName, d.Name)
			w.Print("}")

			w.Print("// Construct a %s from a C %s* found from some exernal source.  It is the caller's responsibility to ensure the pointer lives.", goName, d.Name)
			w.Print("func Borrow%s(p unsafe.Pointer) *%s {", goName, goName)
			w.Print("return &%s{(*C.%s)(p)}", goName, d.Name)
			w.Print("}")
		} else {
			sharedTypes[d.Name] = goName
			w.Print("type %s struct {", goName)
			for _, d := range d.Type.Decls {
				typ := cTypeToMap(d.Type)
				w.Print("%s %s", cNameToGoUpper(d.Name), typ.goType)
			}
			w.Print("}")
		}
	case cc.Enum:
		type constEntry struct {
			goName, cName string
		}
		consts := make([]constEntry, 0, len(d.Type.Decls))
		for _, d := range d.Type.Decls {
			constName := d.Name
			if strings.HasPrefix(constName, "CAIRO_") {
				constName = constName[len("CAIRO_"):]
			}
			constName = cNameToGoUpper(strings.ToLower(d.Name))
			consts = append(consts, constEntry{constName, d.Name})
		}

		w.Print("type %s int", goName)
		w.Print("const (")
		for _, c := range consts {
			w.Print("%s %s = C.%s", c.goName, goName, c.cName)
		}
		w.Print(")")

		if goName != "Status" {
			w.Print("// String implements the Stringer interface, which is used in places like fmt's %%q.  For all enums like this it returns the Go name of the constant.")
			w.Print("func (i %s) String() string {", goName)
			w.Print("switch i {")
			for _, c := range consts {
				w.Print("case %s: return \"%s\"", c.goName, c.goName)
			}
			w.Print("default: return fmt.Sprintf(\"%s(%%d)\", i)", goName)
			w.Print("}")
			w.Print("}")
		}
	default:
		panic("unhandled decl " + d.String())
	}
}