func (this *binding_generator) generate(go_template string) { // this will fill the 'go_bindings' buffer repo := gi.DefaultRepository() for i, n := 0, repo.NumInfo(config.namespace); i < n; i++ { this.process_base_info(repo.Info(config.namespace, i)) } t := must_template(go_template) t.Execute(this.out_go, map[string]interface{}{ "g_object_ref_unref": g_object_ref_unref, "go_utils": go_utils(true), "go_utils_no_cb": go_utils(false), "go_bindings": this.go_bindings.String(), "g_error_free": g_error_free, "g_free": g_free, }) // write source/header preambles p := printer_to(this.out_h) p(c_header) // TODO: using config.pkg here is probably incorrect, we should use the // filename c_template.Execute(this.out_c, map[string]interface{}{ "namespace": config.namespace, "package": config.pkg, }) p = printer_to(this.out_c) p("\n\n") // this will write the rest of .c/.h files this.c_forward_declarations() }
func CForwardDeclarations() string { var out bytes.Buffer printf = PrinterTo(&out) repo := gi.DefaultRepository() deps := repo.Dependencies(Config.Namespace) for _, dep := range deps { depv := strings.Split(dep, "-") _, err := repo.Require(depv[0], depv[1], 0) if err != nil { panic(err) } for i, n := 0, repo.NumInfo(depv[0]); i < n; i++ { CForwardDeclaration10(repo.Info(depv[0], i)) CForwardDeclaration30(repo.Info(depv[0], i)) } } for i, n := 0, repo.NumInfo(Config.Namespace); i < n; i++ { CForwardDeclaration10(repo.Info(Config.Namespace, i)) } for i, n := 0, repo.NumInfo(Config.Namespace); i < n; i++ { CForwardDeclaration20(repo.Info(Config.Namespace, i)) } for i, n := 0, repo.NumInfo(Config.Namespace); i < n; i++ { CForwardDeclaration30(repo.Info(Config.Namespace, i)) } return out.String() }
func (this *binding_generator) c_forward_declarations() { repo := gi.DefaultRepository() deps := repo.Dependencies(config.namespace) for _, dep := range deps { depv := strings.Split(dep, "-") _, err := repo.Require(depv[0], depv[1], 0) if err != nil { panic(err) } for i, n := 0, repo.NumInfo(depv[0]); i < n; i++ { this.c_forward_declaration10(repo.Info(depv[0], i)) this.c_forward_declaration30(repo.Info(depv[0], i)) } } for i, n := 0, repo.NumInfo(config.namespace); i < n; i++ { this.c_forward_declaration10(repo.Info(config.namespace, i)) } for i, n := 0, repo.NumInfo(config.namespace); i < n; i++ { this.c_forward_declaration20(repo.Info(config.namespace, i)) } for i, n := 0, repo.NumInfo(config.namespace); i < n; i++ { this.c_forward_declaration30(repo.Info(config.namespace, i)) } }
func GoToCgoForInterface(bi *gi.BaseInfo, arg0, arg1 string, flags ConvFlags) string { var out bytes.Buffer printf := PrinterTo(&out) switch bi.Type() { case gi.INFO_TYPE_OBJECT: prefix := gi.DefaultRepository().CPrefix(bi.Namespace()) printf("if %s != nil {\n", arg0) printf("\t%s = %s.InheritedFrom%s%s()\n", arg1, arg0, prefix, bi.Name()) printf("}") case gi.INFO_TYPE_ENUM, gi.INFO_TYPE_FLAGS: ctype := CgoTypeForInterface(bi, TypeNone) printf("%s = %s(%s)", arg1, ctype, arg0) case gi.INFO_TYPE_INTERFACE: prefix := gi.DefaultRepository().CPrefix(bi.Namespace()) printf("if %s != nil {\n", arg0) printf("\t%s = %s.Implements%s%s()", arg1, arg0, prefix, bi.Name()) printf("}") case gi.INFO_TYPE_STRUCT: ns := bi.Namespace() if ns == "cairo" { printf(CairoGoToCgoForInterface(bi, arg0, arg1, flags)) break } fullnm := strings.ToLower(ns) + "." + bi.Name() if _, ok := GConfig.Sys.DisguisedTypes[fullnm]; ok { flags &^= ConvPointer } ctype := CgoTypeForInterface(bi, TypeNone) if flags&ConvPointer != 0 { printf("%s = (*%s)(unsafe.Pointer(%s))", arg1, ctype, arg0) } else { printf("%s = *(*%s)(unsafe.Pointer(&%s))", arg1, ctype, arg0) } case gi.INFO_TYPE_CALLBACK: printf("if %s != nil {\n", arg0) printf("\t%s = unsafe.Pointer(&%s)", arg1, arg0) printf("}") } return out.String() }
func GoBindings() string { var out bytes.Buffer printf = PrinterTo(&out) repo := gi.DefaultRepository() for i, n := 0, repo.NumInfo(Config.Namespace); i < n; i++ { ProcessBaseInfo(repo.Info(Config.Namespace, i)) } return out.String() }
func (this *binding_generator) process_object_info(oi *gi.ObjectInfo) { p := printer_to(&this.go_bindings) parent := "C unsafe.Pointer" parentlike := "" if p := oi.Parent(); p != nil { parent = "" if ns := p.Namespace(); ns != config.namespace { parent += strings.ToLower(ns) + "." } parent += p.Name() parentlike = parent + "Like" } // interface that this class and its subclasses implement cprefix := gi.DefaultRepository().CPrefix(config.namespace) name := oi.Name() cgotype := cgo_type_for_interface(gi.ToBaseInfo(oi), type_pointer) var interfaces bytes.Buffer pi := printer_to(&interfaces) for i, n := 0, oi.NumInterface(); i < n; i++ { ii := oi.Interface(i) name := ii.Name() ns := ii.Namespace() if i != 0 { pi("\n\t") } if ns != config.namespace { pi("%s.", strings.ToLower(ns)) } pi("%sImpl", name) } p("%s\n", execute_template(object_template, map[string]string{ "name": name, "cprefix": cprefix, "cgotype": cgotype, "parent": parent, "parentlike": parentlike, "typeinit": oi.TypeInit(), "gobjectns": config.gns, "interfaces": interfaces.String(), })) for i, n := 0, oi.NumMethod(); i < n; i++ { meth := oi.Method(i) if config.is_method_blacklisted(name, meth.Name()) { p("// blacklisted: %s.%s (method)\n", name, meth.Name()) continue } this.process_function_info(meth) } }
func ProcessObjectInfo(oi *gi.ObjectInfo) { parent := "C unsafe.Pointer" parentlike := "" if p := oi.Parent(); p != nil { parent = "" if ns := p.Namespace(); ns != Config.Namespace { parent += strings.ToLower(ns) + "." } parent += p.Name() parentlike = parent + "Like" } // interface that this class and its subclasses implement cprefix := gi.DefaultRepository().CPrefix(Config.Namespace) name := oi.Name() cgotype := CgoTypeForInterface(gi.ToBaseInfo(oi), TypePointer) var interfaces bytes.Buffer for i, n := 0, oi.NumInterface(); i < n; i++ { ii := oi.Interface(i) name := ii.Name() ns := ii.Namespace() if i != 0 { interfaces.WriteString("\n\t") } if ns != Config.Namespace { fmt.Fprintf(&interfaces, "%s.", strings.ToLower(ns)) } fmt.Fprintf(&interfaces, "%sImpl", name) } printf("%s\n", ExecuteTemplate(ObjectTemplate, map[string]string{ "name": name, "cprefix": cprefix, "cgotype": cgotype, "parent": parent, "parentlike": parentlike, "typeinit": oi.TypeInit(), "gobjectns": Config.Sys.GNS, "interfaces": interfaces.String(), })) for i, n := 0, oi.NumMethod(); i < n; i++ { meth := oi.Method(i) if IsMethodBlacklisted(name, meth.Name()) { printf("// blacklisted: %s.%s (method)\n", name, meth.Name()) continue } ProcessFunctionInfo(meth, gi.ToBaseInfo(oi)) } }
func c_type_for_interface(bi *gi.BaseInfo, flags type_flags) string { var out bytes.Buffer ns := bi.Namespace() nm := bi.Name() fullnm := strings.ToLower(ns) + "." + nm out.WriteString(gi.DefaultRepository().CPrefix(ns)) out.WriteString(bi.Name()) if flags&type_pointer != 0 && !config.is_disguised(fullnm) { out.WriteString("*") } return out.String() }
func CTypeForInterface(bi *gi.BaseInfo, flags TypeFlags) string { var out bytes.Buffer ns := bi.Namespace() nm := bi.Name() fullnm := strings.ToLower(ns) + "." + nm out.WriteString(gi.DefaultRepository().CPrefix(ns)) out.WriteString(bi.Name()) _, disguised := GConfig.Sys.DisguisedTypes[fullnm] if flags&TypePointer != 0 && !disguised { out.WriteString("*") } return out.String() }
func main() { sysconfig_path := flag.String("config", "", "specify global config file") output_dir := flag.String("o", "", "override output directory") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s [flags] <dir>\n", os.Args[0]) flag.PrintDefaults() } flag.Parse() if flag.NArg() != 1 { flag.Usage() return } // figure in/out paths in_dir, in_base := filepath.Split(flag.Arg(0)) in_path := flag.Arg(0) out_dir := in_dir if *output_dir != "" { out_dir = *output_dir } out_base := filepath.Join(out_dir, in_base[:len(in_base)-6]) // parse system config file if *sysconfig_path != "" { config.load_sys(*sysconfig_path) } // parse local config config.load(filepath.Join(in_dir, "config.json")) // load namespace _, err := gi.DefaultRepository().Require(config.namespace, config.version, 0) panic_if_error(err) // load go template go_template, err := ioutil.ReadFile(in_path) panic_if_error(err) // generate bindings bg := new_binding_generator(out_base) defer bg.release() bg.generate(string(go_template)) }
func cgo_type_for_interface(bi *gi.BaseInfo, flags type_flags) string { var out bytes.Buffer switch bi.Type() { case gi.INFO_TYPE_CALLBACK: out.WriteString("unsafe.Pointer") default: ns := bi.Namespace() nm := bi.Name() fullnm := strings.ToLower(ns) + "." + nm if flags&type_pointer != 0 && !config.is_disguised(fullnm) { out.WriteString("*") } out.WriteString("C.") out.WriteString(gi.DefaultRepository().CPrefix(ns)) out.WriteString(bi.Name()) } return out.String() }
func ProcessInterfaceInfo(ii *gi.InterfaceInfo) { name := ii.Name() cprefix := gi.DefaultRepository().CPrefix(ii.Namespace()) cgotype := CgoTypeForInterface(gi.ToBaseInfo(ii), TypePointer) printf("%s\n", ExecuteTemplate(InterfaceTemplate, map[string]string{ "name": name, "cprefix": cprefix, "cgotype": cgotype, "typeinit": ii.TypeInit(), "gobjectns": Config.Sys.GNS, })) for i, n := 0, ii.NumMethod(); i < n; i++ { meth := ii.Method(i) if IsMethodBlacklisted(name, meth.Name()) { printf("// blacklisted: %s.%s (method)\n", name, meth.Name()) continue } ProcessFunctionInfo(meth, gi.ToBaseInfo(ii)) } }
func CgoTypeForInterface(bi *gi.BaseInfo, flags TypeFlags) string { var out bytes.Buffer switch bi.Type() { case gi.INFO_TYPE_CALLBACK: out.WriteString("unsafe.Pointer") default: ns := bi.Namespace() nm := bi.Name() fullnm := strings.ToLower(ns) + "." + nm _, disguised := GConfig.Sys.DisguisedTypes[fullnm] if flags&TypePointer != 0 && !disguised { out.WriteString("*") } out.WriteString("C.") out.WriteString(gi.DefaultRepository().CPrefix(ns)) out.WriteString(bi.Name()) } return out.String() }
func (this *binding_generator) process_interface_info(ii *gi.InterfaceInfo) { p := printer_to(&this.go_bindings) name := ii.Name() cprefix := gi.DefaultRepository().CPrefix(ii.Namespace()) cgotype := cgo_type_for_interface(gi.ToBaseInfo(ii), type_pointer) p("%s\n", execute_template(interface_template, map[string]string{ "name": name, "cprefix": cprefix, "cgotype": cgotype, "typeinit": ii.TypeInit(), "gobjectns": config.gns, })) for i, n := 0, ii.NumMethod(); i < n; i++ { meth := ii.Method(i) if config.is_method_blacklisted(name, meth.Name()) { p("// blacklisted: %s.%s (method)\n", name, meth.Name()) continue } this.process_function_info(meth) } }
func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s [flags] <dir>\n", os.Args[0]) flag.PrintDefaults() } flag.Parse() if flag.NArg() != 1 { flag.Usage() return } // parse global config if *GConfigPath != "" { err := ParseJSONWithComments(*GConfigPath, &GConfig) if err != nil { panic(err) } GConfig.Sys.DisguisedTypes = ListToMap(GConfig.DisguisedTypes) } // parse config configPath := filepath.Join(flag.Arg(0), "config.json") err := ParseJSONWithComments(configPath, &Config) if err != nil { panic(err) } repo := gi.DefaultRepository() // load namespace _, err = repo.Require(Config.Namespace, Config.Version, 0) if err != nil { panic(err) } // setup some of the Sys vars Config.Sys.Package = strings.ToLower(Config.Namespace) Config.Sys.Outdir = filepath.Clean(flag.Arg(0)) Config.Sys.Whitelist = MapListToMapMap(Config.Whitelist) Config.Sys.Blacklist = MapListToMapMap(Config.Blacklist) Config.Sys.MethodWhitelist = MapListToMapMap(Config.MethodWhitelist) Config.Sys.MethodBlacklist = MapListToMapMap(Config.MethodBlacklist) if Config.Namespace != "GObject" { Config.Sys.GNS = "gobject." } // prepare main output filename := filepath.Join(Config.Sys.Outdir, strings.ToLower(Config.Namespace)+".go") file, err := os.Create(filename) if err != nil { panic(err) } defer file.Close() Config.Sys.Out = bufio.NewWriter(file) tpl, err := ioutil.ReadFile(filename + ".in") if err != nil { panic(err) } ProcessTemplate(string(tpl)) Config.Sys.Out.Flush() }