From 7df33f4a5c4bc0b8745846b84bbd109d5c8d7ed8 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Fri, 11 Mar 2016 11:52:33 +0100 Subject: [PATCH] mobile/bind: allow bound packages to refer to imported bound packages Multiple packages are already supported, but only as if each packages were bound in isolation. This CL lets a bound package refer to other bound packages in its exported functions, types and fields. In Java, the JNI class jclass and constructor jmethodID are exported so other packages can construct proxies of other packages' interfaces. In ObjC, the class @interface declarations are moved from the package .m file to its .h file to allow other packages to constructs its interface proxies. Add a supporting test package, secondpkg, and add Java and ObjC tests for the new cross package functionality. Also add simplepkg for testing corner cases where the generated Go file must not include its bound package. While we're here, stop generating Go proxy types for struct types; only Go interfaces can be implemented in the foreign language. Change-Id: Icbfa739c893703867d38a9100ed0928fbd7a660d Reviewed-on: https://go-review.googlesource.com/20575 Reviewed-by: David Crawshaw --- bind/bind.go | 49 ++++++------ bind/bind_test.go | 18 ++--- bind/gen.go | 35 ++++++--- bind/gengo.go | 89 ++++++++++++++-------- bind/genjava.go | 94 ++++++++++++++--------- bind/genobjc.go | 97 +++++++++++++----------- bind/java/SeqTest.java | 20 +++++ bind/java/seq_test.go | 12 ++- bind/objc/SeqTest.m | 19 +++++ bind/objc/seq_test.go | 12 ++- bind/testdata/basictypes.java.c.golden | 3 +- bind/testdata/basictypes.objc.m.golden | 2 +- bind/testdata/customprefix.java.c.golden | 3 +- bind/testdata/customprefix.objc.m.golden | 2 +- bind/testdata/interfaces.java.c.golden | 27 ++++--- bind/testdata/interfaces.java.h.golden | 18 +++++ bind/testdata/interfaces.objc.h.golden | 40 ++++++++++ bind/testdata/interfaces.objc.m.golden | 42 +--------- bind/testdata/issue10788.go.golden | 2 - bind/testdata/issue10788.java.c.golden | 11 ++- bind/testdata/issue10788.java.h.golden | 5 ++ bind/testdata/issue10788.objc.h.golden | 11 +++ bind/testdata/issue10788.objc.m.golden | 13 +--- bind/testdata/issue12328.go.golden | 2 - bind/testdata/issue12328.java.c.golden | 7 +- bind/testdata/issue12328.java.h.golden | 2 + bind/testdata/issue12328.objc.m.golden | 2 +- bind/testdata/issue12403.java.c.golden | 7 +- bind/testdata/issue12403.java.h.golden | 3 + bind/testdata/issue12403.objc.h.golden | 11 +++ bind/testdata/issue12403.objc.m.golden | 13 +--- bind/testdata/structs.go.golden | 4 - bind/testdata/structs.java.c.golden | 15 ++-- bind/testdata/structs.java.h.golden | 7 ++ bind/testdata/structs.objc.h.golden | 10 +++ bind/testdata/structs.objc.m.golden | 12 +-- bind/testdata/try.java.c.golden | 3 +- bind/testdata/try.objc.m.golden | 2 +- bind/testdata/vars.go.golden | 2 - bind/testdata/vars.java.c.golden | 11 ++- bind/testdata/vars.java.h.golden | 5 ++ bind/testdata/vars.objc.h.golden | 9 +++ bind/testdata/vars.objc.m.golden | 11 +-- bind/testpkg/secondpkg/secondpkg.go | 25 ++++++ bind/testpkg/simplepkg/simplepkg.go | 16 ++++ bind/testpkg/testpkg.go | 40 ++++++++++ cmd/gobind/gen.go | 28 +++++-- cmd/gobind/main.go | 7 +- cmd/gomobile/bind.go | 42 +++++++--- cmd/gomobile/bind_androidapp.go | 6 +- cmd/gomobile/bind_iosapp.go | 8 +- 51 files changed, 601 insertions(+), 333 deletions(-) create mode 100644 bind/testpkg/secondpkg/secondpkg.go create mode 100644 bind/testpkg/simplepkg/simplepkg.go diff --git a/bind/bind.go b/bind/bind.go index 2990e0c..63ca719 100644 --- a/bind/bind.go +++ b/bind/bind.go @@ -20,7 +20,16 @@ import ( "io" ) -type fileType int +type ( + GeneratorConfig struct { + Writer io.Writer + Fset *token.FileSet + Pkg *types.Package + AllPkg []*types.Package + } + + fileType int +) const ( Java fileType = iota @@ -33,17 +42,15 @@ const ( ) // GenJava generates a Java API from a Go package. -func GenJava(w io.Writer, fset *token.FileSet, pkg *types.Package, javaPkg string, ft fileType) error { - if javaPkg == "" { - javaPkg = javaPkgName(pkg.Name()) - } +func GenJava(conf *GeneratorConfig, javaPkg string, ft fileType) error { buf := new(bytes.Buffer) g := &javaGen{ javaPkg: javaPkg, generator: &generator{ printer: &printer{buf: buf, indentEach: []byte(" ")}, - fset: fset, - pkg: pkg, + fset: conf.Fset, + allPkg: conf.AllPkg, + pkg: conf.Pkg, }, } g.init() @@ -61,18 +68,19 @@ func GenJava(w io.Writer, fset *token.FileSet, pkg *types.Package, javaPkg strin if err != nil { return err } - _, err = io.Copy(w, buf) + _, err = io.Copy(conf.Writer, buf) return err } // GenGo generates a Go stub to support foreign language APIs. -func GenGo(w io.Writer, fset *token.FileSet, pkg *types.Package) error { +func GenGo(conf *GeneratorConfig) error { buf := new(bytes.Buffer) g := &goGen{ - &generator{ + generator: &generator{ printer: &printer{buf: buf, indentEach: []byte("\t")}, - fset: fset, - pkg: pkg, + fset: conf.Fset, + allPkg: conf.AllPkg, + pkg: conf.Pkg, }, } g.init() @@ -82,25 +90,22 @@ func GenGo(w io.Writer, fset *token.FileSet, pkg *types.Package) error { src := buf.Bytes() srcf, err := format.Source(src) if err != nil { - w.Write(src) // for debugging + conf.Writer.Write(src) // for debugging return err } - _, err = w.Write(srcf) + _, err = conf.Writer.Write(srcf) return err } // GenObjc generates the Objective-C API from a Go package. -func GenObjc(w io.Writer, fset *token.FileSet, pkg *types.Package, prefix string, ft fileType) error { - if prefix == "" { - prefix = "Go" - } - +func GenObjc(conf *GeneratorConfig, prefix string, ft fileType) error { buf := new(bytes.Buffer) g := &objcGen{ generator: &generator{ printer: &printer{buf: buf, indentEach: []byte("\t")}, - fset: fset, - pkg: pkg, + fset: conf.Fset, + allPkg: conf.AllPkg, + pkg: conf.Pkg, }, prefix: prefix, } @@ -119,6 +124,6 @@ func GenObjc(w io.Writer, fset *token.FileSet, pkg *types.Package, prefix string if err != nil { return err } - _, err = io.Copy(w, buf) + _, err = io.Copy(conf.Writer, buf) return err } diff --git a/bind/bind_test.go b/bind/bind_test.go index 2a9c480..49b9072 100644 --- a/bind/bind_test.go +++ b/bind/bind_test.go @@ -100,7 +100,7 @@ func TestGenObjc(t *testing.T) { for typ, suffix := range suffixes { var buf bytes.Buffer - if err := GenObjc(&buf, fset, pkg, "", typ); err != nil { + if err := GenObjc(&buf, fset, pkg, []*types.Package{pkg}, "", typ); err != nil { t.Errorf("%s: %v", filename, err) continue } @@ -132,7 +132,7 @@ func TestGenJava(t *testing.T) { pkg := typeCheck(t, filename) for typ, suffix := range suffixes { var buf bytes.Buffer - if err := GenJava(&buf, fset, pkg, "", typ); err != nil { + if err := GenJava(&buf, fset, pkg, []*types.Package{pkg}, "", typ); err != nil { t.Errorf("%s: %v", filename, err) continue } @@ -158,7 +158,7 @@ func TestGenGo(t *testing.T) { for _, filename := range tests { var buf bytes.Buffer pkg := typeCheck(t, filename) - if err := GenGo(&buf, fset, pkg); err != nil { + if err := GenGo(&buf, fset, pkg, []*types.Package{pkg}); err != nil { t.Errorf("%s: %v", filename, err) continue } @@ -189,27 +189,27 @@ func TestCustomPrefix(t *testing.T) { }{ { "testdata/customprefix.java.golden", - func(w io.Writer) error { return GenJava(w, fset, pkg, "com.example", Java) }, + func(w io.Writer) error { return GenJava(w, fset, pkg, []*types.Package{pkg}, "com.example", Java) }, }, { "testdata/customprefix.java.h.golden", - func(w io.Writer) error { return GenJava(w, fset, pkg, "com.example", JavaH) }, + func(w io.Writer) error { return GenJava(w, fset, pkg, []*types.Package{pkg}, "com.example", JavaH) }, }, { "testdata/customprefix.java.c.golden", - func(w io.Writer) error { return GenJava(w, fset, pkg, "com.example", JavaC) }, + func(w io.Writer) error { return GenJava(w, fset, pkg, []*types.Package{pkg}, "com.example", JavaC) }, }, { "testdata/customprefix.objc.go.h.golden", - func(w io.Writer) error { return GenObjc(w, fset, pkg, "EX", ObjcGoH) }, + func(w io.Writer) error { return GenObjc(w, fset, pkg, []*types.Package{pkg}, "EX", ObjcGoH) }, }, { "testdata/customprefix.objc.h.golden", - func(w io.Writer) error { return GenObjc(w, fset, pkg, "EX", ObjcH) }, + func(w io.Writer) error { return GenObjc(w, fset, pkg, []*types.Package{pkg}, "EX", ObjcH) }, }, { "testdata/customprefix.objc.m.golden", - func(w io.Writer) error { return GenObjc(w, fset, pkg, "EX", ObjcM) }, + func(w io.Writer) error { return GenObjc(w, fset, pkg, []*types.Package{pkg}, "EX", ObjcM) }, }, } diff --git a/bind/gen.go b/bind/gen.go index 1a4aec8..2b827d1 100644 --- a/bind/gen.go +++ b/bind/gen.go @@ -52,14 +52,13 @@ func (list ErrorList) Error() string { type generator struct { *printer - fset *token.FileSet - pkg *types.Package - err ErrorList + fset *token.FileSet + allPkg []*types.Package + pkg *types.Package + err ErrorList // fields set by init. - pkgName string - // pkgPrefix is a prefix for disambiguating - // function names for binding multiple packages + pkgName string pkgPrefix string funcs []*types.Func constants []*types.Const @@ -70,12 +69,19 @@ type generator struct { otherNames []*types.TypeName } +// pkgPrefix returns a prefix that disambiguates symbol names for binding +// multiple packages. +// +// TODO(elias.naur): Avoid (and test) name clashes from multiple packages +// with the same name. Perhaps use the index from the order the package is +// generated. +func pkgPrefix(pkg *types.Package) string { + return pkg.Name() +} + func (g *generator) init() { g.pkgName = g.pkg.Name() - // TODO(elias.naur): Avoid (and test) name clashes from multiple packages - // with the same name. Perhaps use the index from the order the package is - // generated. - g.pkgPrefix = g.pkgName + g.pkgPrefix = pkgPrefix(g.pkg) scope := g.pkg.Scope() hasExported := false @@ -223,6 +229,15 @@ func (g *generator) genInterfaceMethodSignature(m *types.Func, iName string, hea } } +func (g *generator) validPkg(pkg *types.Package) bool { + for _, p := range g.allPkg { + if p.Path() == pkg.Path() { + return true + } + } + return false +} + var paramRE = regexp.MustCompile(`^p[0-9]*$`) // paramName replaces incompatible name with a p0-pN name. diff --git a/bind/gengo.go b/bind/gengo.go index 805b559..5544350 100644 --- a/bind/gengo.go +++ b/bind/gengo.go @@ -5,6 +5,7 @@ package bind import ( + "bytes" "fmt" "go/types" "strings" @@ -12,6 +13,7 @@ import ( type goGen struct { *generator + imports map[string]struct{} } const ( @@ -30,14 +32,6 @@ package gomobile_bind */ import "C" -import ( - _seq "golang.org/x/mobile/bind/seq" - %[2]q -) - -// suppress the error if seq ends up unused -var _ = _seq.FromRefNum - ` ) @@ -129,11 +123,6 @@ func (g *goGen) genWrite(toVar, fromVar string, t types.Type, mode varMode) { // TODO(crawshaw): test **Generator switch t := t.Elem().(type) { case *types.Named: - obj := t.Obj() - if obj.Pkg() != g.pkg { - g.errorf("type %s not defined in %s", t, g.pkg) - return - } g.genToRefNum(toVar, fromVar) default: g.errorf("unsupported type %s", t) @@ -193,7 +182,7 @@ func (g *goGen) genFuncSignature(o *types.Func, objName string) { func (g *goGen) genFunc(o *types.Func) { g.genFuncSignature(o, "") g.Indent() - g.genFuncBody(o, g.pkg.Name()) + g.genFuncBody(o, g.pkgName(g.pkg)) g.Outdent() g.Printf("}\n\n") } @@ -202,15 +191,13 @@ func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) { fields := exportedFields(T) methods := exportedMethodSet(types.NewPointer(obj.Type())) - g.Printf("type proxy%s _seq.Ref\n\n", obj.Name()) - for _, f := range fields { g.Printf("//export proxy%s_%s_%s_Set\n", g.pkgPrefix, obj.Name(), f.Name()) g.Printf("func proxy%s_%s_%s_Set(refnum C.int32_t, v C.%s) {\n", g.pkgPrefix, obj.Name(), f.Name(), g.cgoType(f.Type())) g.Indent() g.Printf("ref := _seq.FromRefNum(int32(refnum))\n") g.genRead("_v", "v", f.Type(), modeRetained) - g.Printf("ref.Get().(*%s.%s).%s = _v\n", g.pkg.Name(), obj.Name(), f.Name()) + g.Printf("ref.Get().(*%s.%s).%s = _v\n", g.pkgName(g.pkg), obj.Name(), f.Name()) g.Outdent() g.Printf("}\n\n") @@ -218,7 +205,7 @@ func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) { g.Printf("func proxy%s_%s_%s_Get(refnum C.int32_t) C.%s {\n", g.pkgPrefix, obj.Name(), f.Name(), g.cgoType(f.Type())) g.Indent() g.Printf("ref := _seq.FromRefNum(int32(refnum))\n") - g.Printf("v := ref.Get().(*%s.%s).%s\n", g.pkg.Name(), obj.Name(), f.Name()) + g.Printf("v := ref.Get().(*%s.%s).%s\n", g.pkgName(g.pkg), obj.Name(), f.Name()) g.genWrite("_v", "v", f.Type(), modeRetained) g.Printf("return _v\n") g.Outdent() @@ -229,7 +216,7 @@ func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) { g.genFuncSignature(m, obj.Name()) g.Indent() g.Printf("ref := _seq.FromRefNum(int32(refnum))\n") - g.Printf("v := ref.Get().(*%s.%s)\n", g.pkg.Name(), obj.Name()) + g.Printf("v := ref.Get().(*%s.%s)\n", g.pkgName(g.pkg), obj.Name()) g.genFuncBody(m, "v") g.Outdent() g.Printf("}\n\n") @@ -239,7 +226,7 @@ func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) { func (g *goGen) genVar(o *types.Var) { // TODO(hyangah): non-struct pointer types (*int), struct type. - v := fmt.Sprintf("%s.%s", g.pkg.Name(), o.Name()) + v := fmt.Sprintf("%s.%s", g.pkgName(g.pkg), o.Name()) // var I int // @@ -273,7 +260,7 @@ func (g *goGen) genInterface(obj *types.TypeName) { g.genFuncSignature(m, obj.Name()) g.Indent() g.Printf("ref := _seq.FromRefNum(int32(refnum))\n") - g.Printf("v := ref.Get().(%s.%s)\n", g.pkg.Name(), obj.Name()) + g.Printf("v := ref.Get().(%s.%s)\n", g.pkgName(g.pkg), obj.Name()) g.genFuncBody(m, "v") g.Outdent() g.Printf("}\n\n") @@ -383,13 +370,14 @@ func (g *goGen) genRead(toVar, fromVar string, typ types.Type, mode varMode) { switch u := t.Elem().(type) { case *types.Named: o := u.Obj() - if o.Pkg() != g.pkg { - g.errorf("type %s not defined in %s", u, g.pkg) + oPkg := o.Pkg() + if !g.validPkg(oPkg) { + g.errorf("type %s is defined in %s, which is not bound", u, oPkg) return } g.Printf("// Must be a Go object\n") g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", toVar, fromVar) - g.Printf("%s := %s_ref.Get().(*%s.%s)\n", toVar, toVar, g.pkg.Name(), o.Name()) + g.Printf("%s := %s_ref.Get().(*%s.%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name()) default: g.errorf("unsupported pointer type %s", t) } @@ -401,18 +389,19 @@ func (g *goGen) genRead(toVar, fromVar string, typ types.Type, mode varMode) { hasProxy = makeIfaceSummary(iface).implementable } o := t.Obj() - if o.Pkg() != g.pkg { - g.errorf("type %s not defined in %s", t, g.pkg) + oPkg := o.Pkg() + if !g.validPkg(oPkg) { + g.errorf("type %s is defined in %s, which is not bound", t, oPkg) return } g.Printf("var %s %s\n", toVar, g.typeString(t)) g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", toVar, fromVar) g.Printf("if %s_ref != nil {\n", toVar) g.Printf(" if %s_ref.Num < 0 { // go object \n", toVar) - g.Printf(" %s = %s_ref.Get().(%s.%s)\n", toVar, toVar, g.pkg.Name(), o.Name()) + g.Printf(" %s = %s_ref.Get().(%s.%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name()) if hasProxy { g.Printf(" } else { // foreign object \n") - g.Printf(" %s = (*proxy%s_%s)(%s_ref)\n", toVar, g.pkgPrefix, o.Name(), toVar) + g.Printf(" %s = (*proxy%s_%s)(%s_ref)\n", toVar, pkgPrefix(oPkg), o.Name(), toVar) } g.Printf(" }\n") g.Printf("}\n") @@ -433,13 +422,15 @@ func (g *goGen) typeString(typ types.Type) string { if obj.Pkg() == nil { // e.g. error type is *types.Named. return types.TypeString(typ, types.RelativeTo(pkg)) } - if obj.Pkg() != g.pkg { - g.errorf("type %s not defined in %s", t, g.pkg) + oPkg := obj.Pkg() + if !g.validPkg(oPkg) { + g.errorf("type %s is defined in %s, which is not bound", t, oPkg) + return "TODO" } switch t.Underlying().(type) { case *types.Interface, *types.Struct: - return fmt.Sprintf("%s.%s", pkg.Name(), types.TypeString(typ, types.RelativeTo(pkg))) + return fmt.Sprintf("%s.%s", g.pkgName(oPkg), types.TypeString(typ, types.RelativeTo(oPkg))) default: g.errorf("unsupported named type %s / %T", t, t) } @@ -456,8 +447,30 @@ func (g *goGen) typeString(typ types.Type) string { return "" } -func (g *goGen) gen() error { +// genPreamble generates the preamble. It is generated after everything +// else, where we know which bound packages to import. +func (g *goGen) genPreamble() { g.Printf(goPreamble, g.pkg.Name(), g.pkg.Path()) + g.Printf("import (\n") + g.Indent() + g.Printf("_seq \"golang.org/x/mobile/bind/seq\"\n") + for path := range g.imports { + g.Printf("%q\n", path) + } + g.Outdent() + g.Printf(")\n\n") +} + +func (g *goGen) gen() error { + g.imports = make(map[string]struct{}) + + // Switch to a temporary buffer so the preamble can be + // written last. + oldBuf := g.printer.buf + newBuf := new(bytes.Buffer) + g.printer.buf = newBuf + g.Printf("// suppress the error if seq ends up unused\n") + g.Printf("var _ = _seq.FromRefNum\n") for _, s := range g.structs { g.genStruct(s.obj, s.t) @@ -471,8 +484,20 @@ func (g *goGen) gen() error { for _, f := range g.funcs { g.genFunc(f) } + // Switch to the original buffer, write the preamble + // and append the rest of the file. + g.printer.buf = oldBuf + g.genPreamble() + g.printer.buf.Write(newBuf.Bytes()) if len(g.err) > 0 { return g.err } return nil } + +// pkgName retuns the package name and adds the package to the list of +// imports. +func (g *goGen) pkgName(pkg *types.Package) string { + g.imports[pkg.Path()] = struct{}{} + return pkg.Name() +} diff --git a/bind/genjava.go b/bind/genjava.go index 3749bc2..9603780 100644 --- a/bind/genjava.go +++ b/bind/genjava.go @@ -16,6 +16,8 @@ import ( // TODO(crawshaw): consider introducing Java functions for casting to and from interfaces at runtime. type javaGen struct { + // javaPkg is the custom name of the Java pkg that contains the generated classes. If empty, + // use a package name generated from the Go package name. javaPkg string *generator @@ -262,22 +264,24 @@ func (g *javaGen) javaType(T types.Type) string { if _, ok := T.Elem().(*types.Named); ok { return g.javaType(T.Elem()) } - panic(fmt.Sprintf("unsupported pointer to type: %s", T)) + g.errorf("unsupported pointer to type: %s", T) case *types.Named: n := T.Obj() - if n.Pkg() != g.pkg { - nPkgName := "" - if nPkg := n.Pkg(); nPkg != nil { - nPkgName = nPkg.Name() - } - panic(fmt.Sprintf("type %s is in package %s, must be defined in package %s", n.Name(), nPkgName, g.pkg.Name())) + nPkg := n.Pkg() + if !g.validPkg(nPkg) { + g.errorf("type %s is in %s, which is not bound", n.Name(), nPkg) + break } // TODO(crawshaw): more checking here - return n.Name() + if nPkg != g.pkg { + return fmt.Sprintf("%s.%s.%s", g.javaPkgName(nPkg), className(nPkg), n.Name()) + } else { + return n.Name() + } default: g.errorf("unsupported javaType: %#+v, %s\n", T, T) - return "TODO" } + return "TODO" } func (g *javaGen) genJNIFuncSignature(o *types.Func, sName string, proxy bool) { @@ -328,7 +332,7 @@ func (g *javaGen) genJNIFuncSignature(o *types.Func, sName string, proxy bool) { } func (g *javaGen) jniPkgName() string { - return strings.Replace(g.javaPkg, ".", "_", -1) + return strings.Replace(g.javaPkgName(g.pkg), ".", "_", -1) } func (g *javaGen) genFuncSignature(o *types.Func, static, header bool) { @@ -466,24 +470,14 @@ func (g *javaGen) genCToJava(toName, fromName string, t types.Type, mode varMode // TODO(crawshaw): test **Generator switch t := t.Elem().(type) { case *types.Named: - o := t.Obj() - if o.Pkg() != g.pkg { - g.errorf("type %s not defined in %s", t, g.pkg) - return - } - g.Printf("jobject %s = go_seq_from_refnum(env, %s, proxy_class_%s_%s, proxy_class_%s_%s_cons);\n", toName, fromName, g.pkgPrefix, o.Name(), g.pkgPrefix, o.Name()) + g.genFromRefnum(toName, fromName, t, t.Obj()) default: g.errorf("unsupported type %s", t) } case *types.Named: switch t.Underlying().(type) { case *types.Interface, *types.Pointer: - o := t.Obj() - if o.Pkg() != g.pkg { - g.errorf("type %s not defined in %s", t, g.pkg) - return - } - g.Printf("jobject %s = go_seq_from_refnum(env, %s, proxy_class_%s_%s, proxy_class_%s_%s_cons);\n", toName, fromName, g.pkgPrefix, o.Name(), g.pkgPrefix, o.Name()) + g.genFromRefnum(toName, fromName, t, t.Obj()) default: g.errorf("unsupported, direct named type %s", t) } @@ -492,9 +486,19 @@ func (g *javaGen) genCToJava(toName, fromName string, t types.Type, mode varMode } } +func (g *javaGen) genFromRefnum(toName, fromName string, t types.Type, o *types.TypeName) { + oPkg := o.Pkg() + if !g.validPkg(oPkg) { + g.errorf("type %s is defined in package %s, which is not bound", t, oPkg) + return + } + p := pkgPrefix(oPkg) + g.Printf("jobject %s = go_seq_from_refnum(env, %s, proxy_class_%s_%s, proxy_class_%s_%s_cons);\n", toName, fromName, p, o.Name(), p, o.Name()) +} + func (g *javaGen) gobindOpts() string { opts := []string{"-lang=java"} - if g.javaPkg != javaPkgName(g.pkg.Name()) { + if g.javaPkg != "" { opts = append(opts, "-javapkg="+g.javaPkg) } return strings.Join(opts, " ") @@ -505,8 +509,11 @@ var javaNameReplacer = strings.NewReplacer( ".", "_", ) -func javaPkgName(pkgName string) string { - s := javaNameReplacer.Replace(pkgName) +func (g *javaGen) javaPkgName(pkg *types.Package) string { + if g.javaPkg != "" { + return g.javaPkg + } + s := javaNameReplacer.Replace(pkg.Name()) // Look for Java keywords that are not Go keywords, and avoid using // them as a package name. // @@ -528,7 +535,11 @@ func javaPkgName(pkgName string) string { } func (g *javaGen) className() string { - return strings.Title(javaNameReplacer.Replace(g.pkg.Name())) + return className(g.pkg) +} + +func className(pkg *types.Package) string { + return strings.Title(javaNameReplacer.Replace(pkg.Name())) } func (g *javaGen) genConst(o *types.Const) { @@ -749,11 +760,18 @@ func (g *javaGen) genMethodInterfaceProxy(oName string, m *types.Func) { func (g *javaGen) genH() error { g.Printf(hPreamble, g.gobindOpts(), g.pkg.Path(), g.className()) for _, iface := range g.interfaces { + g.Printf("extern jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name()) + g.Printf("extern jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name()) + g.Printf("\n") for _, m := range iface.summary.callable { g.genInterfaceMethodSignature(m, iface.obj.Name(), true) g.Printf("\n") } } + for _, s := range g.structs { + g.Printf("extern jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name()) + g.Printf("extern jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name()) + } g.Printf("#endif\n") if len(g.err) > 0 { return g.err @@ -805,7 +823,7 @@ func (g *javaGen) jniCallType(t types.Type) string { } func (g *javaGen) jniClassSigType(className string) string { - return strings.Replace(g.javaPkg, ".", "/", -1) + "/" + g.className() + "$" + className + return strings.Replace(g.javaPkgName(g.pkg), ".", "/", -1) + "/" + g.className() + "$" + className } func (g *javaGen) jniSigType(T types.Type) string { @@ -856,16 +874,24 @@ func (g *javaGen) jniSigType(T types.Type) string { func (g *javaGen) genC() error { g.Printf(cPreamble, g.gobindOpts(), g.pkg.Path(), g.pkg.Name()) + g.Printf("#include %q\n", g.pkg.Name()+".h") + for _, pkg := range g.pkg.Imports() { + if g.validPkg(pkg) { + g.Printf("#include \"%s.h\"\n", pkg.Name()) + } + } + g.Printf("\n") + for _, iface := range g.interfaces { - g.Printf("static jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name()) - g.Printf("static jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name()) + g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name()) + g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name()) for i := 0; i < iface.t.NumMethods(); i++ { g.Printf("static jmethodID mid_%s_%s;\n", iface.obj.Name(), iface.t.Method(i).Name()) } } for _, s := range g.structs { - g.Printf("static jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name()) - g.Printf("static jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name()) + g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name()) + g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name()) } g.Printf("\n") g.Printf("JNIEXPORT void JNICALL\n") @@ -931,7 +957,7 @@ func (g *javaGen) genC() error { } func (g *javaGen) genJava() error { - g.Printf(javaPreamble, g.javaPkg, g.className(), g.gobindOpts(), g.pkg.Path()) + g.Printf(javaPreamble, g.javaPkgName(g.pkg), g.className(), g.gobindOpts(), g.pkg.Path()) g.Printf("public abstract class %s {\n", g.className()) g.Indent() @@ -996,11 +1022,9 @@ import go.Seq; #include #include #include "seq.h" -#include "%[3]s.h" #include "_cgo_export.h" - - ` + hPreamble = `// JNI function headers for the Go <=> Java bridge. // gobind %[1]s %[2]s // diff --git a/bind/genobjc.go b/bind/genobjc.go index ab0fee2..824f6ce 100644 --- a/bind/genobjc.go +++ b/bind/genobjc.go @@ -43,7 +43,15 @@ type structInfo struct { func (g *objcGen) init() { g.generator.init() - g.namePrefix = g.prefix + strings.Title(g.pkgName) + g.namePrefix = g.namePrefixOf(g.pkg) +} + +func (g *objcGen) namePrefixOf(pkg *types.Package) string { + p := g.prefix + if p == "" { + p = "Go" + } + return p + strings.Title(pkg.Name()) } func (g *objcGen) genGoH() error { @@ -73,10 +81,15 @@ func (g *objcGen) genGoH() error { func (g *objcGen) genH() error { g.Printf(objcPreamble, g.pkg.Path(), g.gobindOpts(), g.pkg.Path()) - g.Printf("#ifndef __%s%s_H__\n", g.prefix, strings.Title(g.pkgName)) - g.Printf("#define __%s%s_H__\n", g.prefix, strings.Title(g.pkgName)) + g.Printf("#ifndef __%s_H__\n", g.namePrefix) + g.Printf("#define __%s_H__\n", g.namePrefix) g.Printf("\n") g.Printf("#include \n") + for _, pkg := range g.pkg.Imports() { + if g.validPkg(pkg) { + g.Printf("#include %q\n", g.namePrefixOf(pkg)+".h") + } + } g.Printf("\n") // Forward declaration of @class and @protocol @@ -136,39 +149,6 @@ func (g *objcGen) genH() error { g.Printf("\n") } - // declare all named types first. - g.Printf("#endif\n") - - if len(g.err) > 0 { - return g.err - } - return nil -} - -func (g *objcGen) gobindOpts() string { - opts := []string{"-lang=objc"} - if g.prefix != "Go" { - opts = append(opts, "-prefix="+g.prefix) - } - return strings.Join(opts, " ") -} - -func (g *objcGen) genM() error { - g.Printf(objcPreamble, g.pkg.Path(), g.gobindOpts(), g.pkg.Path()) - g.Printf("#include %q\n", g.namePrefix+".h") - g.Printf("#include \n") - g.Printf("#include \"seq.h\"\n") - g.Printf("#include \"_cgo_export.h\"\n") - g.Printf("\n") - g.Printf("static NSString* errDomain = @\"go.%s\";\n", g.pkg.Path()) - g.Printf("\n") - g.Printf(`@protocol goSeqRefInterface --(GoSeqRef*) _ref; -@end - -`) - - // forward declarations skipped from genH for _, i := range g.interfaces { if i.summary.implementable { g.Printf("@class %s%s;\n\n", g.namePrefix, i.obj.Name()) @@ -182,6 +162,37 @@ func (g *objcGen) genM() error { } } + g.Printf("#endif\n") + + if len(g.err) > 0 { + return g.err + } + return nil +} + +func (g *objcGen) gobindOpts() string { + opts := []string{"-lang=objc"} + if g.prefix != "" { + opts = append(opts, "-prefix="+g.prefix) + } + return strings.Join(opts, " ") +} + +func (g *objcGen) genM() error { + g.Printf(objcPreamble, g.pkg.Path(), g.gobindOpts(), g.pkg.Path()) + g.Printf("#include \n") + g.Printf("#include \"seq.h\"\n") + g.Printf("#include \"_cgo_export.h\"\n") + g.Printf("#include %q\n", g.namePrefix+".h") + g.Printf("\n") + g.Printf("static NSString* errDomain = @\"go.%s\";\n", g.pkg.Path()) + g.Printf("\n") + g.Printf(`@protocol goSeqRefInterface +-(GoSeqRef*) _ref; +@end + +`) + // struct for _, s := range g.structs { g.genStructM(s.obj, s.t) @@ -889,10 +900,10 @@ func (g *objcGen) refTypeBase(typ types.Type) string { } case *types.Named: n := typ.Obj() - if n.Pkg() == g.pkg { + if g.validPkg(n.Pkg()) { switch typ.Underlying().(type) { case *types.Interface, *types.Struct: - return g.namePrefix + n.Name() + return g.namePrefixOf(n.Pkg()) + n.Name() } } } @@ -965,19 +976,19 @@ func (g *objcGen) objcType(typ types.Type) string { return "TODO" case *types.Named: n := typ.Obj() - if n.Pkg() != g.pkg { - g.errorf("type %s is in package %s; only types defined in package %s is supported", n.Name(), n.Pkg().Name(), g.pkg.Name()) + if !g.validPkg(n.Pkg()) { + g.errorf("type %s is in package %s, which is not bound", n.Name(), n.Pkg().Name()) return "TODO" } switch t := typ.Underlying().(type) { case *types.Interface: if makeIfaceSummary(t).implementable { - return "id<" + g.namePrefix + n.Name() + ">" + return "id<" + g.namePrefixOf(n.Pkg()) + n.Name() + ">" } else { - return g.namePrefix + n.Name() + "*" + return g.namePrefixOf(n.Pkg()) + n.Name() + "*" } case *types.Struct: - return g.namePrefix + n.Name() + return g.namePrefixOf(n.Pkg()) + n.Name() } g.errorf("unsupported, named type %s", typ) return "TODO" diff --git a/bind/java/SeqTest.java b/bind/java/SeqTest.java index 474591a..1647508 100644 --- a/bind/java/SeqTest.java +++ b/bind/java/SeqTest.java @@ -11,6 +11,7 @@ import java.util.Arrays; import java.util.Random; import go.testpkg.Testpkg; +import go.secondpkg.Secondpkg; public class SeqTest extends InstrumentationTestCase { public SeqTest() { @@ -472,4 +473,23 @@ public class SeqTest extends InstrumentationTestCase { } }); } + + public void testImportedPkg() { + assertEquals("imported string should match", Secondpkg.HelloString, Secondpkg.Hello()); + Secondpkg.I i = Testpkg.NewImportedI(); + Secondpkg.S s = Testpkg.NewImportedS(); + i = Testpkg.getImportedVarI(); + s = Testpkg.getImportedVarS(); + assertEquals("numbers should match", 8, i.F(8)); + assertEquals("numbers should match", 8, s.F(8)); + Testpkg.setImportedVarI(i); + Testpkg.setImportedVarS(s); + Testpkg.ImportedFields fields = Testpkg.NewImportedFields(); + i = fields.getI(); + s = fields.getS(); + fields.setI(i); + fields.setS(s); + Testpkg.WithImportedI(i); + Testpkg.WithImportedS(s); + } } diff --git a/bind/java/seq_test.go b/bind/java/seq_test.go index 1c39c89..5535fcb 100644 --- a/bind/java/seq_test.go +++ b/bind/java/seq_test.go @@ -20,7 +20,11 @@ import ( // This requires the gradle command in PATH and // the Android SDK whose path is available through ANDROID_HOME environment variable. func TestJavaSeqTest(t *testing.T) { - runTest(t, "golang.org/x/mobile/bind/testpkg", "SeqTest") + runTest(t, []string{ + "golang.org/x/mobile/bind/testpkg", + "golang.org/x/mobile/bind/testpkg/secondpkg", + "golang.org/x/mobile/bind/testpkg/simplepkg", + }, "SeqTest") } // TestJavaSeqBench runs java test SeqBench.java, with the same @@ -34,10 +38,10 @@ func TestJavaSeqTest(t *testing.T) { // // while running the benchmark to see the results. func TestJavaSeqBench(t *testing.T) { - runTest(t, "golang.org/x/mobile/bind/benchmark", "SeqBench") + runTest(t, []string{"golang.org/x/mobile/bind/benchmark"}, "SeqBench") } -func runTest(t *testing.T, pkgName, javaCls string) { +func runTest(t *testing.T, pkgNames []string, javaCls string) { if _, err := run("which gradle"); err != nil { t.Skip("command gradle not found, skipping") } @@ -80,7 +84,7 @@ func runTest(t *testing.T, pkgName, javaCls string) { } } - buf, err := run("gomobile bind -o pkg.aar " + pkgName) + buf, err := run("gomobile bind -o pkg.aar " + strings.Join(pkgNames, " ")) if err != nil { t.Logf("%s", buf) t.Fatalf("failed to run gomobile bind: %v", err) diff --git a/bind/objc/SeqTest.m b/bind/objc/SeqTest.m index 69bda57..89b2d4f 100644 --- a/bind/objc/SeqTest.m +++ b/bind/objc/SeqTest.m @@ -348,4 +348,23 @@ static int numI = 0; XCTAssertEqualObjects(got, want, @"want %@\nGoTestpkgReturnsError(TRUE) = (%@, %@)", want, value, got); } +- (void)testImportedPkg { + XCTAssertEqualObjects(GoSecondpkgHelloString, GoSecondpkgHello(), @"imported string should match"); + id i = GoTestpkgNewImportedI(); + GoSecondpkgS *s = GoTestpkgNewImportedS(); + XCTAssertEqual(8, [i f:8], @"numbers should match"); + XCTAssertEqual(8, [s f:8], @"numbers should match"); + i = GoTestpkgWithImportedI(i); + s = GoTestpkgWithImportedS(s); + i = [GoTestpkg importedVarI]; + s = [GoTestpkg importedVarS]; + [GoTestpkg setImportedVarI:i]; + [GoTestpkg setImportedVarS:s]; + GoTestpkgImportedFields *fields = GoTestpkgNewImportedFields(); + i = [fields i]; + s = [fields s]; + [fields setI:i]; + [fields setS:s]; +} + @end diff --git a/bind/objc/seq_test.go b/bind/objc/seq_test.go index a143ab1..2a1a014 100644 --- a/bind/objc/seq_test.go +++ b/bind/objc/seq_test.go @@ -38,16 +38,20 @@ var destination = flag.String("device", "platform=iOS Simulator,name=iPhone 6s P // TestObjcSeqTest runs ObjC test SeqTest.m. // This requires the xcode command lines tools. func TestObjcSeqTest(t *testing.T) { - runTest(t, "golang.org/x/mobile/bind/testpkg", "xcodetest", "SeqTest.m", false) + runTest(t, []string{ + "golang.org/x/mobile/bind/testpkg", + "golang.org/x/mobile/bind/testpkg/secondpkg", + "golang.org/x/mobile/bind/testpkg/simplepkg", + }, "xcodetest", "SeqTest.m", false) } // TestObjcSeqBench runs ObjC test SeqBench.m. // This requires the xcode command lines tools. func TestObjcSeqBench(t *testing.T) { - runTest(t, "golang.org/x/mobile/bind/benchmark", "xcodebench", "SeqBench.m", true) + runTest(t, []string{"golang.org/x/mobile/bind/benchmark"}, "xcodebench", "SeqBench.m", true) } -func runTest(t *testing.T, pkgName, project, testfile string, dumpOutput bool) { +func runTest(t *testing.T, pkgNames []string, project, testfile string, dumpOutput bool) { if _, err := run("which xcodebuild"); err != nil { t.Skip("command xcodebuild not found, skipping") } @@ -89,7 +93,7 @@ func runTest(t *testing.T, pkgName, project, testfile string, dumpOutput bool) { } defer os.Chdir(cwd) - buf, err := run("gomobile bind -target=ios " + pkgName) + buf, err := run("gomobile bind -target=ios " + strings.Join(pkgNames, " ")) if err != nil { t.Logf("%s", buf) t.Fatalf("failed to run gomobile bind: %v", err) diff --git a/bind/testdata/basictypes.java.c.golden b/bind/testdata/basictypes.java.c.golden index 5690011..caa1d1e 100644 --- a/bind/testdata/basictypes.java.c.golden +++ b/bind/testdata/basictypes.java.c.golden @@ -6,9 +6,8 @@ #include #include #include "seq.h" -#include "basictypes.h" #include "_cgo_export.h" - +#include "basictypes.h" JNIEXPORT void JNICALL diff --git a/bind/testdata/basictypes.objc.m.golden b/bind/testdata/basictypes.objc.m.golden index d3b7b4e..0c9bcb5 100644 --- a/bind/testdata/basictypes.objc.m.golden +++ b/bind/testdata/basictypes.objc.m.golden @@ -3,10 +3,10 @@ // // File is generated by gobind. Do not edit. -#include "GoBasictypes.h" #include #include "seq.h" #include "_cgo_export.h" +#include "GoBasictypes.h" static NSString* errDomain = @"go.basictypes"; diff --git a/bind/testdata/customprefix.java.c.golden b/bind/testdata/customprefix.java.c.golden index a8ba32b..00074b9 100644 --- a/bind/testdata/customprefix.java.c.golden +++ b/bind/testdata/customprefix.java.c.golden @@ -6,9 +6,8 @@ #include #include #include "seq.h" -#include "customprefix.h" #include "_cgo_export.h" - +#include "customprefix.h" JNIEXPORT void JNICALL diff --git a/bind/testdata/customprefix.objc.m.golden b/bind/testdata/customprefix.objc.m.golden index 59f8583..13041d2 100644 --- a/bind/testdata/customprefix.objc.m.golden +++ b/bind/testdata/customprefix.objc.m.golden @@ -3,10 +3,10 @@ // // File is generated by gobind. Do not edit. -#include "EXCustomprefix.h" #include #include "seq.h" #include "_cgo_export.h" +#include "EXCustomprefix.h" static NSString* errDomain = @"go.customprefix"; diff --git a/bind/testdata/interfaces.java.c.golden b/bind/testdata/interfaces.java.c.golden index 202c1fe..777586a 100644 --- a/bind/testdata/interfaces.java.c.golden +++ b/bind/testdata/interfaces.java.c.golden @@ -6,29 +6,28 @@ #include #include #include "seq.h" -#include "interfaces.h" #include "_cgo_export.h" +#include "interfaces.h" - -static jclass proxy_class_interfaces_Error; -static jmethodID proxy_class_interfaces_Error_cons; +jclass proxy_class_interfaces_Error; +jmethodID proxy_class_interfaces_Error_cons; static jmethodID mid_Error_Err; -static jclass proxy_class_interfaces_I; -static jmethodID proxy_class_interfaces_I_cons; +jclass proxy_class_interfaces_I; +jmethodID proxy_class_interfaces_I_cons; static jmethodID mid_I_Rand; -static jclass proxy_class_interfaces_I1; -static jmethodID proxy_class_interfaces_I1_cons; +jclass proxy_class_interfaces_I1; +jmethodID proxy_class_interfaces_I1_cons; static jmethodID mid_I1_H; static jmethodID mid_I1_J; -static jclass proxy_class_interfaces_I2; -static jmethodID proxy_class_interfaces_I2_cons; +jclass proxy_class_interfaces_I2; +jmethodID proxy_class_interfaces_I2_cons; static jmethodID mid_I2_G; static jmethodID mid_I2_f; -static jclass proxy_class_interfaces_I3; -static jmethodID proxy_class_interfaces_I3_cons; +jclass proxy_class_interfaces_I3; +jmethodID proxy_class_interfaces_I3_cons; static jmethodID mid_I3_F; -static jclass proxy_class_interfaces_WithParam; -static jmethodID proxy_class_interfaces_WithParam_cons; +jclass proxy_class_interfaces_WithParam; +jmethodID proxy_class_interfaces_WithParam_cons; static jmethodID mid_WithParam_HasParam; JNIEXPORT void JNICALL diff --git a/bind/testdata/interfaces.java.h.golden b/bind/testdata/interfaces.java.h.golden index 6e05bd7..df496ea 100644 --- a/bind/testdata/interfaces.java.h.golden +++ b/bind/testdata/interfaces.java.h.golden @@ -8,16 +8,34 @@ #include +extern jclass proxy_class_interfaces_Error; +extern jmethodID proxy_class_interfaces_Error_cons; + nstring cproxyinterfaces_Error_Err(int32_t refnum); +extern jclass proxy_class_interfaces_I; +extern jmethodID proxy_class_interfaces_I_cons; + int32_t cproxyinterfaces_I_Rand(int32_t refnum); +extern jclass proxy_class_interfaces_I1; +extern jmethodID proxy_class_interfaces_I1_cons; + void cproxyinterfaces_I1_J(int32_t refnum); +extern jclass proxy_class_interfaces_I2; +extern jmethodID proxy_class_interfaces_I2_cons; + void cproxyinterfaces_I2_G(int32_t refnum); +extern jclass proxy_class_interfaces_I3; +extern jmethodID proxy_class_interfaces_I3_cons; + int32_t cproxyinterfaces_I3_F(int32_t refnum); +extern jclass proxy_class_interfaces_WithParam; +extern jmethodID proxy_class_interfaces_WithParam_cons; + void cproxyinterfaces_WithParam_HasParam(int32_t refnum, char p0); #endif diff --git a/bind/testdata/interfaces.objc.h.golden b/bind/testdata/interfaces.objc.h.golden index bdf25ea..9e75266 100644 --- a/bind/testdata/interfaces.objc.h.golden +++ b/bind/testdata/interfaces.objc.h.golden @@ -57,4 +57,44 @@ FOUNDATION_EXPORT BOOL GoInterfacesCallErr(id e, NSError** er FOUNDATION_EXPORT id GoInterfacesSeven(); +@class GoInterfacesError; + +@class GoInterfacesI; + +@class GoInterfacesI3; + +@class GoInterfacesWithParam; + +@interface GoInterfacesError : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +- (BOOL)err:(NSError**)error; +@end + +@interface GoInterfacesI : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +- (int32_t)rand; +@end + +@interface GoInterfacesI3 : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +- (GoInterfacesI1*)f; +@end + +@interface GoInterfacesWithParam : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +- (void)hasParam:(BOOL)p0; +@end + #endif diff --git a/bind/testdata/interfaces.objc.m.golden b/bind/testdata/interfaces.objc.m.golden index c112f60..d89926d 100644 --- a/bind/testdata/interfaces.objc.m.golden +++ b/bind/testdata/interfaces.objc.m.golden @@ -3,10 +3,10 @@ // // File is generated by gobind. Do not edit. -#include "GoInterfaces.h" #include #include "seq.h" #include "_cgo_export.h" +#include "GoInterfaces.h" static NSString* errDomain = @"go.interfaces"; @@ -14,46 +14,6 @@ static NSString* errDomain = @"go.interfaces"; -(GoSeqRef*) _ref; @end -@class GoInterfacesError; - -@class GoInterfacesI; - -@class GoInterfacesI3; - -@class GoInterfacesWithParam; - -@interface GoInterfacesError : NSObject { -} -@property(strong, readonly) id _ref; - -- (id)initWithRef:(id)ref; -- (BOOL)err:(NSError**)error; -@end - -@interface GoInterfacesI : NSObject { -} -@property(strong, readonly) id _ref; - -- (id)initWithRef:(id)ref; -- (int32_t)rand; -@end - -@interface GoInterfacesI3 : NSObject { -} -@property(strong, readonly) id _ref; - -- (id)initWithRef:(id)ref; -- (GoInterfacesI1*)f; -@end - -@interface GoInterfacesWithParam : NSObject { -} -@property(strong, readonly) id _ref; - -- (id)initWithRef:(id)ref; -- (void)hasParam:(BOOL)p0; -@end - @implementation GoInterfacesError { } diff --git a/bind/testdata/issue10788.go.golden b/bind/testdata/issue10788.go.golden index 0981a16..19c86dd 100644 --- a/bind/testdata/issue10788.go.golden +++ b/bind/testdata/issue10788.go.golden @@ -21,8 +21,6 @@ import ( // suppress the error if seq ends up unused var _ = _seq.FromRefNum -type proxyTestStruct _seq.Ref - //export proxyissue10788_TestStruct_Value_Set func proxyissue10788_TestStruct_Value_Set(refnum C.int32_t, v C.nstring) { ref := _seq.FromRefNum(int32(refnum)) diff --git a/bind/testdata/issue10788.java.c.golden b/bind/testdata/issue10788.java.c.golden index 9d63edc..48e179f 100644 --- a/bind/testdata/issue10788.java.c.golden +++ b/bind/testdata/issue10788.java.c.golden @@ -6,16 +6,15 @@ #include #include #include "seq.h" -#include "issue10788.h" #include "_cgo_export.h" +#include "issue10788.h" - -static jclass proxy_class_issue10788_TestInterface; -static jmethodID proxy_class_issue10788_TestInterface_cons; +jclass proxy_class_issue10788_TestInterface; +jmethodID proxy_class_issue10788_TestInterface_cons; static jmethodID mid_TestInterface_DoSomeWork; static jmethodID mid_TestInterface_MultipleUnnamedParams; -static jclass proxy_class_issue10788_TestStruct; -static jmethodID proxy_class_issue10788_TestStruct_cons; +jclass proxy_class_issue10788_TestStruct; +jmethodID proxy_class_issue10788_TestStruct_cons; JNIEXPORT void JNICALL Java_go_issue10788_Issue10788_init(JNIEnv *env, jclass _unused) { diff --git a/bind/testdata/issue10788.java.h.golden b/bind/testdata/issue10788.java.h.golden index 895f15f..f8206d3 100644 --- a/bind/testdata/issue10788.java.h.golden +++ b/bind/testdata/issue10788.java.h.golden @@ -8,8 +8,13 @@ #include +extern jclass proxy_class_issue10788_TestInterface; +extern jmethodID proxy_class_issue10788_TestInterface_cons; + void cproxyissue10788_TestInterface_DoSomeWork(int32_t refnum, int32_t s); void cproxyissue10788_TestInterface_MultipleUnnamedParams(int32_t refnum, nint p0, nstring p1, int64_t p2); +extern jclass proxy_class_issue10788_TestStruct; +extern jmethodID proxy_class_issue10788_TestStruct_cons; #endif diff --git a/bind/testdata/issue10788.objc.h.golden b/bind/testdata/issue10788.objc.h.golden index eea9159..c391329 100644 --- a/bind/testdata/issue10788.objc.h.golden +++ b/bind/testdata/issue10788.objc.h.golden @@ -26,4 +26,15 @@ - (void)multipleUnnamedParams:(int)p0 p1:(NSString*)p1 p2:(int64_t)p2; @end +@class GoIssue10788TestInterface; + +@interface GoIssue10788TestInterface : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +- (void)doSomeWork:(GoIssue10788TestStruct*)s; +- (void)multipleUnnamedParams:(int)p0 p1:(NSString*)p1 p2:(int64_t)p2; +@end + #endif diff --git a/bind/testdata/issue10788.objc.m.golden b/bind/testdata/issue10788.objc.m.golden index 7671140..d48e481 100644 --- a/bind/testdata/issue10788.objc.m.golden +++ b/bind/testdata/issue10788.objc.m.golden @@ -3,10 +3,10 @@ // // File is generated by gobind. Do not edit. -#include "GoIssue10788.h" #include #include "seq.h" #include "_cgo_export.h" +#include "GoIssue10788.h" static NSString* errDomain = @"go.issue10788"; @@ -14,17 +14,6 @@ static NSString* errDomain = @"go.issue10788"; -(GoSeqRef*) _ref; @end -@class GoIssue10788TestInterface; - -@interface GoIssue10788TestInterface : NSObject { -} -@property(strong, readonly) id _ref; - -- (id)initWithRef:(id)ref; -- (void)doSomeWork:(GoIssue10788TestStruct*)s; -- (void)multipleUnnamedParams:(int)p0 p1:(NSString*)p1 p2:(int64_t)p2; -@end - @implementation GoIssue10788TestStruct { } diff --git a/bind/testdata/issue12328.go.golden b/bind/testdata/issue12328.go.golden index 65ce4c8..4a238f7 100644 --- a/bind/testdata/issue12328.go.golden +++ b/bind/testdata/issue12328.go.golden @@ -21,8 +21,6 @@ import ( // suppress the error if seq ends up unused var _ = _seq.FromRefNum -type proxyT _seq.Ref - //export proxyissue12328_T_Err_Set func proxyissue12328_T_Err_Set(refnum C.int32_t, v C.nstring) { ref := _seq.FromRefNum(int32(refnum)) diff --git a/bind/testdata/issue12328.java.c.golden b/bind/testdata/issue12328.java.c.golden index 8aca32a..52b110d 100644 --- a/bind/testdata/issue12328.java.c.golden +++ b/bind/testdata/issue12328.java.c.golden @@ -6,12 +6,11 @@ #include #include #include "seq.h" -#include "issue12328.h" #include "_cgo_export.h" +#include "issue12328.h" - -static jclass proxy_class_issue12328_T; -static jmethodID proxy_class_issue12328_T_cons; +jclass proxy_class_issue12328_T; +jmethodID proxy_class_issue12328_T_cons; JNIEXPORT void JNICALL Java_go_issue12328_Issue12328_init(JNIEnv *env, jclass _unused) { diff --git a/bind/testdata/issue12328.java.h.golden b/bind/testdata/issue12328.java.h.golden index 0d54708..14debbb 100644 --- a/bind/testdata/issue12328.java.h.golden +++ b/bind/testdata/issue12328.java.h.golden @@ -8,4 +8,6 @@ #include +extern jclass proxy_class_issue12328_T; +extern jmethodID proxy_class_issue12328_T_cons; #endif diff --git a/bind/testdata/issue12328.objc.m.golden b/bind/testdata/issue12328.objc.m.golden index 05095e8..860a132 100644 --- a/bind/testdata/issue12328.objc.m.golden +++ b/bind/testdata/issue12328.objc.m.golden @@ -3,10 +3,10 @@ // // File is generated by gobind. Do not edit. -#include "GoIssue12328.h" #include #include "seq.h" #include "_cgo_export.h" +#include "GoIssue12328.h" static NSString* errDomain = @"go.issue12328"; diff --git a/bind/testdata/issue12403.java.c.golden b/bind/testdata/issue12403.java.c.golden index b8d9e98..569a5ba 100644 --- a/bind/testdata/issue12403.java.c.golden +++ b/bind/testdata/issue12403.java.c.golden @@ -6,12 +6,11 @@ #include #include #include "seq.h" -#include "issue12403.h" #include "_cgo_export.h" +#include "issue12403.h" - -static jclass proxy_class_issue12403_Parsable; -static jmethodID proxy_class_issue12403_Parsable_cons; +jclass proxy_class_issue12403_Parsable; +jmethodID proxy_class_issue12403_Parsable_cons; static jmethodID mid_Parsable_FromJSON; static jmethodID mid_Parsable_ToJSON; diff --git a/bind/testdata/issue12403.java.h.golden b/bind/testdata/issue12403.java.h.golden index a2f7fbb..1b79ac5 100644 --- a/bind/testdata/issue12403.java.h.golden +++ b/bind/testdata/issue12403.java.h.golden @@ -8,6 +8,9 @@ #include +extern jclass proxy_class_issue12403_Parsable; +extern jmethodID proxy_class_issue12403_Parsable_cons; + nstring cproxyissue12403_Parsable_FromJSON(int32_t refnum, nstring jstr); typedef struct cproxyissue12403_Parsable_ToJSON_return { diff --git a/bind/testdata/issue12403.objc.h.golden b/bind/testdata/issue12403.objc.h.golden index 5e7eba5..cb81a42 100644 --- a/bind/testdata/issue12403.objc.h.golden +++ b/bind/testdata/issue12403.objc.h.golden @@ -16,4 +16,15 @@ - (BOOL)toJSON:(NSString**)ret0_ error:(NSError**)error; @end +@class GoIssue12403Parsable; + +@interface GoIssue12403Parsable : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +- (NSString*)fromJSON:(NSString*)jstr; +- (BOOL)toJSON:(NSString**)ret0_ error:(NSError**)error; +@end + #endif diff --git a/bind/testdata/issue12403.objc.m.golden b/bind/testdata/issue12403.objc.m.golden index c568668..35a4cf0 100644 --- a/bind/testdata/issue12403.objc.m.golden +++ b/bind/testdata/issue12403.objc.m.golden @@ -3,10 +3,10 @@ // // File is generated by gobind. Do not edit. -#include "GoIssue12403.h" #include #include "seq.h" #include "_cgo_export.h" +#include "GoIssue12403.h" static NSString* errDomain = @"go.issue12403"; @@ -14,17 +14,6 @@ static NSString* errDomain = @"go.issue12403"; -(GoSeqRef*) _ref; @end -@class GoIssue12403Parsable; - -@interface GoIssue12403Parsable : NSObject { -} -@property(strong, readonly) id _ref; - -- (id)initWithRef:(id)ref; -- (NSString*)fromJSON:(NSString*)jstr; -- (BOOL)toJSON:(NSString**)ret0_ error:(NSError**)error; -@end - @implementation GoIssue12403Parsable { } diff --git a/bind/testdata/structs.go.golden b/bind/testdata/structs.go.golden index 4ec9ca0..9a8eb37 100644 --- a/bind/testdata/structs.go.golden +++ b/bind/testdata/structs.go.golden @@ -21,8 +21,6 @@ import ( // suppress the error if seq ends up unused var _ = _seq.FromRefNum -type proxyS _seq.Ref - //export proxystructs_S_X_Set func proxystructs_S_X_Set(refnum C.int32_t, v C.double) { ref := _seq.FromRefNum(int32(refnum)) @@ -81,8 +79,6 @@ func proxystructs_S_Sum(refnum C.int32_t) C.double { return _res_0 } -type proxyS2 _seq.Ref - //export proxystructs_S2_M func proxystructs_S2_M(refnum C.int32_t) { ref := _seq.FromRefNum(int32(refnum)) diff --git a/bind/testdata/structs.java.c.golden b/bind/testdata/structs.java.c.golden index a54d17f..9710738 100644 --- a/bind/testdata/structs.java.c.golden +++ b/bind/testdata/structs.java.c.golden @@ -6,17 +6,16 @@ #include #include #include "seq.h" -#include "structs.h" #include "_cgo_export.h" +#include "structs.h" - -static jclass proxy_class_structs_I; -static jmethodID proxy_class_structs_I_cons; +jclass proxy_class_structs_I; +jmethodID proxy_class_structs_I_cons; static jmethodID mid_I_M; -static jclass proxy_class_structs_S; -static jmethodID proxy_class_structs_S_cons; -static jclass proxy_class_structs_S2; -static jmethodID proxy_class_structs_S2_cons; +jclass proxy_class_structs_S; +jmethodID proxy_class_structs_S_cons; +jclass proxy_class_structs_S2; +jmethodID proxy_class_structs_S2_cons; JNIEXPORT void JNICALL Java_go_structs_Structs_init(JNIEnv *env, jclass _unused) { diff --git a/bind/testdata/structs.java.h.golden b/bind/testdata/structs.java.h.golden index 25ea098..b80a847 100644 --- a/bind/testdata/structs.java.h.golden +++ b/bind/testdata/structs.java.h.golden @@ -8,6 +8,13 @@ #include +extern jclass proxy_class_structs_I; +extern jmethodID proxy_class_structs_I_cons; + void cproxystructs_I_M(int32_t refnum); +extern jclass proxy_class_structs_S; +extern jmethodID proxy_class_structs_S_cons; +extern jclass proxy_class_structs_S2; +extern jmethodID proxy_class_structs_S2_cons; #endif diff --git a/bind/testdata/structs.objc.h.golden b/bind/testdata/structs.objc.h.golden index cfc9f75..7b0a834 100644 --- a/bind/testdata/structs.objc.h.golden +++ b/bind/testdata/structs.objc.h.golden @@ -42,4 +42,14 @@ FOUNDATION_EXPORT GoStructsS* GoStructsIdentity(GoStructsS* s); FOUNDATION_EXPORT BOOL GoStructsIdentityWithError(GoStructsS* s, GoStructsS** ret0_, NSError** error); +@class GoStructsI; + +@interface GoStructsI : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +- (void)m; +@end + #endif diff --git a/bind/testdata/structs.objc.m.golden b/bind/testdata/structs.objc.m.golden index e15d42b..6e8e7df 100644 --- a/bind/testdata/structs.objc.m.golden +++ b/bind/testdata/structs.objc.m.golden @@ -3,10 +3,10 @@ // // File is generated by gobind. Do not edit. -#include "GoStructs.h" #include #include "seq.h" #include "_cgo_export.h" +#include "GoStructs.h" static NSString* errDomain = @"go.structs"; @@ -14,16 +14,6 @@ static NSString* errDomain = @"go.structs"; -(GoSeqRef*) _ref; @end -@class GoStructsI; - -@interface GoStructsI : NSObject { -} -@property(strong, readonly) id _ref; - -- (id)initWithRef:(id)ref; -- (void)m; -@end - @implementation GoStructsS { } diff --git a/bind/testdata/try.java.c.golden b/bind/testdata/try.java.c.golden index 8107f1d..f83c963 100644 --- a/bind/testdata/try.java.c.golden +++ b/bind/testdata/try.java.c.golden @@ -6,9 +6,8 @@ #include #include #include "seq.h" -#include "try.h" #include "_cgo_export.h" - +#include "try.h" JNIEXPORT void JNICALL diff --git a/bind/testdata/try.objc.m.golden b/bind/testdata/try.objc.m.golden index cecba96..8bf633e 100644 --- a/bind/testdata/try.objc.m.golden +++ b/bind/testdata/try.objc.m.golden @@ -3,10 +3,10 @@ // // File is generated by gobind. Do not edit. -#include "GoTry.h" #include #include "seq.h" #include "_cgo_export.h" +#include "GoTry.h" static NSString* errDomain = @"go.try"; diff --git a/bind/testdata/vars.go.golden b/bind/testdata/vars.go.golden index 0f9c16e..f830109 100644 --- a/bind/testdata/vars.go.golden +++ b/bind/testdata/vars.go.golden @@ -21,8 +21,6 @@ import ( // suppress the error if seq ends up unused var _ = _seq.FromRefNum -type proxyS _seq.Ref - type proxyvars_I _seq.Ref //export var_setvars_ABool diff --git a/bind/testdata/vars.java.c.golden b/bind/testdata/vars.java.c.golden index 7bbda6d..5a4a4f3 100644 --- a/bind/testdata/vars.java.c.golden +++ b/bind/testdata/vars.java.c.golden @@ -6,14 +6,13 @@ #include #include #include "seq.h" -#include "vars.h" #include "_cgo_export.h" +#include "vars.h" - -static jclass proxy_class_vars_I; -static jmethodID proxy_class_vars_I_cons; -static jclass proxy_class_vars_S; -static jmethodID proxy_class_vars_S_cons; +jclass proxy_class_vars_I; +jmethodID proxy_class_vars_I_cons; +jclass proxy_class_vars_S; +jmethodID proxy_class_vars_S_cons; JNIEXPORT void JNICALL Java_go_vars_Vars_init(JNIEnv *env, jclass _unused) { diff --git a/bind/testdata/vars.java.h.golden b/bind/testdata/vars.java.h.golden index 6ef9a45..f707a99 100644 --- a/bind/testdata/vars.java.h.golden +++ b/bind/testdata/vars.java.h.golden @@ -8,4 +8,9 @@ #include +extern jclass proxy_class_vars_I; +extern jmethodID proxy_class_vars_I_cons; + +extern jclass proxy_class_vars_S; +extern jmethodID proxy_class_vars_S_cons; #endif diff --git a/bind/testdata/vars.objc.h.golden b/bind/testdata/vars.objc.h.golden index 6a9645f..e5b24ef 100644 --- a/bind/testdata/vars.objc.h.golden +++ b/bind/testdata/vars.objc.h.golden @@ -61,4 +61,13 @@ @end +@class GoVarsI; + +@interface GoVarsI : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +@end + #endif diff --git a/bind/testdata/vars.objc.m.golden b/bind/testdata/vars.objc.m.golden index 5d87788..bb84cae 100644 --- a/bind/testdata/vars.objc.m.golden +++ b/bind/testdata/vars.objc.m.golden @@ -3,10 +3,10 @@ // // File is generated by gobind. Do not edit. -#include "GoVars.h" #include #include "seq.h" #include "_cgo_export.h" +#include "GoVars.h" static NSString* errDomain = @"go.vars"; @@ -14,15 +14,6 @@ static NSString* errDomain = @"go.vars"; -(GoSeqRef*) _ref; @end -@class GoVarsI; - -@interface GoVarsI : NSObject { -} -@property(strong, readonly) id _ref; - -- (id)initWithRef:(id)ref; -@end - @implementation GoVarsS { } diff --git a/bind/testpkg/secondpkg/secondpkg.go b/bind/testpkg/secondpkg/secondpkg.go new file mode 100644 index 0000000..ae87e11 --- /dev/null +++ b/bind/testpkg/secondpkg/secondpkg.go @@ -0,0 +1,25 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package secondpkg is imported by bind tests that verify +// that a bound package can reference another bound package. +package secondpkg + +type ( + I interface { + F(i int) int + } + + S struct{} +) + +func (_ *S) F(i int) int { + return i +} + +const HelloString = "secondpkg string" + +func Hello() string { + return HelloString +} diff --git a/bind/testpkg/simplepkg/simplepkg.go b/bind/testpkg/simplepkg/simplepkg.go new file mode 100644 index 0000000..730c1be --- /dev/null +++ b/bind/testpkg/simplepkg/simplepkg.go @@ -0,0 +1,16 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package simplepkg is imported from testpkg and tests two +// corner cases. +// First: simplepkg itself contains no (exported) functions +// or methods and so its generated Go package must not import +// it. +// +// Second: even though testpkg imports simplepkg, testpkg's +// generated Go package ends up not referencing simplepkg and +// must not import it. +package simplepkg + +type S struct{} diff --git a/bind/testpkg/testpkg.go b/bind/testpkg/testpkg.go index 2333b24..9599d54 100644 --- a/bind/testpkg/testpkg.go +++ b/bind/testpkg/testpkg.go @@ -20,6 +20,9 @@ import ( "time" "golang.org/x/mobile/asset" + + "golang.org/x/mobile/bind/testpkg/secondpkg" + "golang.org/x/mobile/bind/testpkg/simplepkg" ) const ( @@ -411,3 +414,40 @@ type NullFieldStruct struct { func NewNullFieldStruct() *NullFieldStruct { return &NullFieldStruct{} } + +var ( + ImportedVarI secondpkg.I = NewImportedI() + ImportedVarS *secondpkg.S = NewImportedS() +) + +type ImportedFields struct { + I secondpkg.I + S *secondpkg.S +} + +func NewImportedFields() *ImportedFields { + return &ImportedFields{ + I: NewImportedI(), + S: NewImportedS(), + } +} + +func NewImportedI() secondpkg.I { + return NewImportedS() +} + +func NewImportedS() *secondpkg.S { + return new(secondpkg.S) +} + +func WithImportedI(i secondpkg.I) secondpkg.I { + return i +} + +func WithImportedS(s *secondpkg.S) *secondpkg.S { + return s +} + +func NewSimpleS() *simplepkg.S { + return nil +} diff --git a/cmd/gobind/gen.go b/cmd/gobind/gen.go index 6b7624f..5dd1d05 100644 --- a/cmd/gobind/gen.go +++ b/cmd/gobind/gen.go @@ -16,36 +16,48 @@ import ( "golang.org/x/mobile/bind" ) -func genPkg(p *types.Package) { +func genPkg(p *types.Package, allPkg []*types.Package) { fname := defaultFileName(*lang, p) + conf := &bind.GeneratorConfig{ + Fset: fset, + Pkg: p, + AllPkg: allPkg, + } switch *lang { case "java": w, closer := writer(fname) - processErr(bind.GenJava(w, fset, p, *javaPkg, bind.Java)) + conf.Writer = w + processErr(bind.GenJava(conf, *javaPkg, bind.Java)) closer() cname := "java_" + p.Name() + ".c" w, closer = writer(cname) - processErr(bind.GenJava(w, fset, p, *javaPkg, bind.JavaC)) + conf.Writer = w + processErr(bind.GenJava(conf, *javaPkg, bind.JavaC)) closer() hname := p.Name() + ".h" w, closer = writer(hname) - processErr(bind.GenJava(w, fset, p, *javaPkg, bind.JavaH)) + conf.Writer = w + processErr(bind.GenJava(conf, *javaPkg, bind.JavaH)) closer() case "go": w, closer := writer(fname) - processErr(bind.GenGo(w, fset, p)) + conf.Writer = w + processErr(bind.GenGo(conf)) closer() case "objc": gohname := p.Name() + ".h" w, closer := writer(gohname) - processErr(bind.GenObjc(w, fset, p, *prefix, bind.ObjcGoH)) + conf.Writer = w + processErr(bind.GenObjc(conf, *prefix, bind.ObjcGoH)) closer() hname := fname[:len(fname)-2] + ".h" w, closer = writer(hname) - processErr(bind.GenObjc(w, fset, p, *prefix, bind.ObjcH)) + conf.Writer = w + processErr(bind.GenObjc(conf, *prefix, bind.ObjcH)) closer() w, closer = writer(fname) - processErr(bind.GenObjc(w, fset, p, *prefix, bind.ObjcM)) + conf.Writer = w + processErr(bind.GenObjc(conf, *prefix, bind.ObjcM)) closer() default: errorf("unknown target language: %q", *lang) diff --git a/cmd/gobind/main.go b/cmd/gobind/main.go index 8dd5172..a4c4f98 100644 --- a/cmd/gobind/main.go +++ b/cmd/gobind/main.go @@ -8,6 +8,7 @@ import ( "flag" "fmt" "go/importer" + "go/types" "log" "os" "os/exec" @@ -46,13 +47,17 @@ func main() { os.Exit(1) } + var allPkg []*types.Package for _, arg := range flag.Args() { pkg, err := importer.Default().Import(arg) if err != nil { fmt.Fprintf(os.Stderr, "could not import package %s: %v", arg, err) os.Exit(1) } - genPkg(pkg) + allPkg = append(allPkg, pkg) + } + for _, pkg := range allPkg { + genPkg(pkg, allPkg) } os.Exit(exitStatus) } diff --git a/cmd/gomobile/bind.go b/cmd/gomobile/bind.go index 41cacb5..5b2b62c 100644 --- a/cmd/gomobile/bind.go +++ b/cmd/gomobile/bind.go @@ -160,7 +160,7 @@ func (b *binder) GenObjcSupport(outdir string) error { return copyFile(filepath.Join(outdir, "seq.h"), filepath.Join(objcPkg.Dir, "seq.h")) } -func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) { +func (b *binder) GenObjc(pkg *types.Package, allPkg []*types.Package, outdir string) (string, error) { const bindPrefixDefault = "Go" if bindPrefix == "" { bindPrefix = bindPrefixDefault @@ -176,6 +176,11 @@ func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) { hfile := filepath.Join(outdir, fileBase+".h") gohfile := filepath.Join(outdir, pkg.Name()+".h") + conf := &bind.GeneratorConfig{ + Fset: b.fset, + Pkg: pkg, + AllPkg: allPkg, + } generate := func(w io.Writer) error { if buildX { printcmd("gobind %s -outdir=%s %s", bindOption, outdir, pkg.Path()) @@ -183,7 +188,8 @@ func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) { if buildN { return nil } - return bind.GenObjc(w, b.fset, pkg, bindPrefix, bind.ObjcM) + conf.Writer = w + return bind.GenObjc(conf, bindPrefix, bind.ObjcM) } if err := writeFile(mfile, generate); err != nil { return "", err @@ -192,7 +198,8 @@ func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) { if buildN { return nil } - return bind.GenObjc(w, b.fset, pkg, bindPrefix, bind.ObjcH) + conf.Writer = w + return bind.GenObjc(conf, bindPrefix, bind.ObjcH) } if err := writeFile(hfile, generate); err != nil { return "", err @@ -201,7 +208,8 @@ func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) { if buildN { return nil } - return bind.GenObjc(w, b.fset, pkg, bindPrefix, bind.ObjcGoH) + conf.Writer = w + return bind.GenObjc(conf, bindPrefix, bind.ObjcGoH) } if err := writeFile(gohfile, generate); err != nil { return "", err @@ -224,7 +232,7 @@ func (b *binder) GenJavaSupport(outdir string) error { return copyFile(filepath.Join(outdir, "seq.h"), filepath.Join(javaPkg.Dir, "seq.h")) } -func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error { +func (b *binder) GenJava(pkg *types.Package, allPkg []*types.Package, outdir, javadir string) error { className := strings.Title(pkg.Name()) javaFile := filepath.Join(javadir, className+".java") cFile := filepath.Join(outdir, "java_"+pkg.Name()+".c") @@ -234,6 +242,11 @@ func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error { bindOption += " -javapkg=" + bindJavaPkg } + conf := &bind.GeneratorConfig{ + Fset: b.fset, + Pkg: pkg, + AllPkg: allPkg, + } generate := func(w io.Writer) error { if buildX { printcmd("gobind %s -outdir=%s %s", bindOption, javadir, pkg.Path()) @@ -241,7 +254,8 @@ func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error { if buildN { return nil } - return bind.GenJava(w, b.fset, pkg, bindJavaPkg, bind.Java) + conf.Writer = w + return bind.GenJava(conf, bindJavaPkg, bind.Java) } if err := writeFile(javaFile, generate); err != nil { return err @@ -250,7 +264,8 @@ func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error { if buildN { return nil } - return bind.GenJava(w, b.fset, pkg, bindJavaPkg, bind.JavaC) + conf.Writer = w + return bind.GenJava(conf, bindJavaPkg, bind.JavaC) } if err := writeFile(cFile, generate); err != nil { return err @@ -259,12 +274,13 @@ func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error { if buildN { return nil } - return bind.GenJava(w, b.fset, pkg, bindJavaPkg, bind.JavaH) + conf.Writer = w + return bind.GenJava(conf, bindJavaPkg, bind.JavaH) } return writeFile(hFile, generate) } -func (b *binder) GenGo(pkg *types.Package, outdir string) error { +func (b *binder) GenGo(pkg *types.Package, allPkg []*types.Package, outdir string) error { pkgName := "go_" + pkg.Name() goFile := filepath.Join(outdir, pkgName+"main.go") @@ -275,7 +291,13 @@ func (b *binder) GenGo(pkg *types.Package, outdir string) error { if buildN { return nil } - return bind.GenGo(w, b.fset, pkg) + conf := &bind.GeneratorConfig{ + Writer: w, + Fset: b.fset, + Pkg: pkg, + AllPkg: allPkg, + } + return bind.GenGo(conf) } if err := writeFile(goFile, generate); err != nil { return err diff --git a/cmd/gomobile/bind_androidapp.go b/cmd/gomobile/bind_androidapp.go index bd86a1a..e6d8568 100644 --- a/cmd/gomobile/bind_androidapp.go +++ b/cmd/gomobile/bind_androidapp.go @@ -71,8 +71,8 @@ func goAndroidBind(pkgs []*build.Package, androidArchs []string) error { } srcDir := filepath.Join(tmpdir, "gomobile_bind") - for _, pkg := range typesPkgs { - if err := binder.GenGo(pkg, srcDir); err != nil { + for _, pkg := range binder.pkgs { + if err := binder.GenGo(pkg, binder.pkgs, srcDir); err != nil { return err } } @@ -96,7 +96,7 @@ func goAndroidBind(pkgs []*build.Package, androidArchs []string) error { if bindJavaPkg == "" { pkgpath = "go/" + pkg.Name() } - if err := binder.GenJava(pkg, srcDir, filepath.Join(androidDir, "src/main/java/"+pkgpath)); err != nil { + if err := binder.GenJava(pkg, binder.pkgs, srcDir, filepath.Join(androidDir, "src/main/java/"+pkgpath)); err != nil { return err } } diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 0c706a7..1ec010c 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -36,8 +36,8 @@ func goIOSBind(pkgs []*build.Package) error { } srcDir := filepath.Join(tmpdir, "src", "gomobile_bind") - for _, pkg := range typesPkgs { - if err := binder.GenGo(pkg, srcDir); err != nil { + for _, pkg := range binder.pkgs { + if err := binder.GenGo(pkg, binder.pkgs, srcDir); err != nil { return err } } @@ -51,8 +51,8 @@ func goIOSBind(pkgs []*build.Package) error { } fileBases := make([]string, len(typesPkgs)) - for i, pkg := range typesPkgs { - if fileBases[i], err = binder.GenObjc(pkg, srcDir); err != nil { + for i, pkg := range binder.pkgs { + if fileBases[i], err = binder.GenObjc(pkg, binder.pkgs, srcDir); err != nil { return err } }