diff --git a/bind/bind_test.go b/bind/bind_test.go index 73bca05..cf6d009 100644 --- a/bind/bind_test.go +++ b/bind/bind_test.go @@ -223,14 +223,7 @@ func genObjcPackages(t *testing.T, dir string, types []*objc.Named, buf *bytes.B return cg } -func genJavaPackages(t *testing.T, dir string, classes []*java.Class, buf *bytes.Buffer) *ClassGen { - cg := &ClassGen{ - Printer: &Printer{ - IndentEach: []byte("\t"), - Buf: buf, - }, - } - cg.Init(classes) +func genJavaPackages(t *testing.T, dir string, cg *ClassGen) { pkgBase := filepath.Join(dir, "src", "Java") if err := os.MkdirAll(pkgBase, 0700); err != nil { t.Fatal(err) @@ -241,16 +234,16 @@ func genJavaPackages(t *testing.T, dir string, classes []*java.Class, buf *bytes t.Fatal(err) } pkgFile := filepath.Join(pkgDir, "package.go") - buf.Reset() + cg.Buf.Reset() cg.GenPackage(i) - if err := ioutil.WriteFile(pkgFile, buf.Bytes(), 0600); err != nil { + if err := ioutil.WriteFile(pkgFile, cg.Buf.Bytes(), 0600); err != nil { t.Fatal(err) } } - buf.Reset() + cg.Buf.Reset() cg.GenInterfaces() clsFile := filepath.Join(pkgBase, "interfaces.go") - if err := ioutil.WriteFile(clsFile, buf.Bytes(), 0600); err != nil { + if err := ioutil.WriteFile(clsFile, cg.Buf.Bytes(), 0600); err != nil { t.Fatal(err) } @@ -264,7 +257,6 @@ func genJavaPackages(t *testing.T, dir string, classes []*java.Class, buf *bytes if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("failed to go install the generated Java wrappers: %v: %s", err, string(out)) } - return cg } func TestGenJava(t *testing.T) { @@ -274,7 +266,10 @@ func TestGenJava(t *testing.T) { } for _, filename := range allTests { refs := fileRefs(t, filename, "Java/") - classes, err := java.Import("", "", refs) + imp := &java.Importer{ + JavaPkgPrefix: "go.", + } + classes, err := imp.Import(refs) if err != nil { t.Fatal(err) } @@ -287,7 +282,18 @@ func TestGenJava(t *testing.T) { t.Fatal(err) } defer os.RemoveAll(tmpGopath) - cg = genJavaPackages(t, tmpGopath, classes, new(bytes.Buffer)) + cg = &ClassGen{ + Printer: &Printer{ + IndentEach: []byte("\t"), + Buf: new(bytes.Buffer), + }, + } + var genNames []string + for _, emb := range refs.Embedders { + genNames = append(genNames, imp.JavaPkgPrefix+emb.Pkg+"."+emb.Name) + } + cg.Init(classes, genNames) + genJavaPackages(t, tmpGopath, cg) cg.Buf = &buf } pkg := typeCheck(t, filename, tmpGopath) @@ -374,7 +380,10 @@ func TestGenGoJavaWrappers(t *testing.T) { for _, filename := range javaTests { var buf bytes.Buffer refs := fileRefs(t, filename, "Java/") - classes, err := java.Import("", "", refs) + imp := &java.Importer{ + JavaPkgPrefix: "go.", + } + classes, err := imp.Import(refs) if err != nil { t.Fatal(err) } @@ -383,7 +392,18 @@ func TestGenGoJavaWrappers(t *testing.T) { t.Fatal(err) } defer os.RemoveAll(tmpGopath) - cg := genJavaPackages(t, tmpGopath, classes, &buf) + cg := &ClassGen{ + Printer: &Printer{ + IndentEach: []byte("\t"), + Buf: &buf, + }, + } + var genNames []string + for _, emb := range refs.Embedders { + genNames = append(genNames, imp.JavaPkgPrefix+emb.Pkg+"."+emb.Name) + } + cg.Init(classes, genNames) + genJavaPackages(t, tmpGopath, cg) pkg := typeCheck(t, filename, tmpGopath) cg.GenGo() testGenGo(t, filename, &buf, pkg) diff --git a/bind/genclasses.go b/bind/genclasses.go index 409e5eb..c7a144c 100644 --- a/bind/genclasses.go +++ b/bind/genclasses.go @@ -34,6 +34,8 @@ type ( // For each Go package path, the Java class with static functions // or constants. clsPkgs map[string]*java.Class + // supers is the map of classes that need Super methods + supers map[string]struct{} } ) @@ -95,7 +97,14 @@ func (g *ClassGen) goType(t *java.Type, local bool) string { } } -func (g *ClassGen) Init(classes []*java.Class) { +// Init initializes the class wrapper generator. Classes is the +// list of classes to wrap, supers is the list of class names +// that need Super methods. +func (g *ClassGen) Init(classes []*java.Class, supers []string) { + g.supers = make(map[string]struct{}) + for _, s := range supers { + g.supers[s] = struct{}{} + } g.classes = classes g.imported = make(map[string]struct{}) g.typePkgs = make(map[string][]*java.Class) @@ -210,7 +219,7 @@ func (g *ClassGen) GenH() { g.Printf("extern ") g.genCMethodDecl("cproxy", cls.JNIName, f) g.Printf(";\n") - if cls.HasSuper() { + if _, ok := g.supers[cls.Name]; ok { g.Printf("extern ") g.genCMethodDecl("csuper", cls.JNIName, f) g.Printf(";\n") @@ -227,9 +236,15 @@ func (g *ClassGen) GenC() { for _, cls := range g.classes { g.genC(cls) g.Printf("static jclass class_%s;\n", cls.JNIName) + if _, ok := g.supers[cls.Name]; ok { + g.Printf("static jclass sclass_%s;\n", cls.JNIName) + } for _, f := range cls.AllMethods { if g.isFuncSupported(f) { g.Printf("static jmethodID m_%s_%s;\n", cls.JNIName, f.JNIName) + if _, ok := g.supers[cls.Name]; ok { + g.Printf("static jmethodID sm_%s_%s;\n", cls.JNIName, f.JNIName) + } } } } @@ -241,9 +256,16 @@ func (g *ClassGen) GenC() { for _, cls := range g.classes { g.Printf("clazz = (*env)->FindClass(env, %q);\n", strings.Replace(cls.FindName, ".", "/", -1)) g.Printf("class_%s = (*env)->NewGlobalRef(env, clazz);\n", cls.JNIName) + if _, ok := g.supers[cls.Name]; ok { + g.Printf("sclass_%s = (*env)->GetSuperclass(env, clazz);\n", cls.JNIName) + g.Printf("sclass_%s = (*env)->NewGlobalRef(env, sclass_%s);\n", cls.JNIName, cls.JNIName) + } for _, f := range cls.AllMethods { if g.isFuncSupported(f) { g.Printf("m_%s_%s = go_seq_get_method_id(clazz, %q, %q);\n", cls.JNIName, f.JNIName, f.Name, f.Desc) + if _, ok := g.supers[cls.Name]; ok { + g.Printf("sm_%s_%s = go_seq_get_method_id(sclass_%s, %q, %q);\n", cls.JNIName, f.JNIName, cls.JNIName, f.Name, f.Desc) + } } } } @@ -257,7 +279,7 @@ func (g *ClassGen) GenC() { } g.genCMethodDecl("cproxy", cls.JNIName, f) g.genCMethodBody(cls, f, false) - if cls.HasSuper() { + if _, ok := g.supers[cls.Name]; ok { g.genCMethodDecl("csuper", cls.JNIName, f) g.genCMethodBody(cls, f, true) } @@ -296,9 +318,10 @@ func (g *ClassGen) genCMethodBody(cls *java.Class, f *java.Func, virtual bool) { } g.Printf("Method(env, _this, ") if virtual { - g.Printf("class_%s, ", cls.JNIName) + g.Printf("sclass_%s, sm_%s_%s", cls.JNIName, cls.JNIName, f.JNIName) + } else { + g.Printf("m_%s_%s", cls.JNIName, f.JNIName) } - g.Printf("m_%s_%s", cls.JNIName, f.JNIName) for i := range f.Params { g.Printf(", _a%d", i) } @@ -509,7 +532,7 @@ func (g *ClassGen) genGo(cls *java.Class) { g.Printf(" return p.ToString()\n") g.Printf("}\n") } - if cls.HasSuper() { + if _, ok := g.supers[cls.Name]; ok { g.Printf("func (p *proxy_class_%s) Super() Java.%s {\n", cls.JNIName, goClsName(cls.Name)) g.Printf(" return &super_%s{p}\n", cls.JNIName) g.Printf("}\n\n") @@ -693,7 +716,7 @@ func (g *ClassGen) genInterface(cls *java.Class) { g.genFuncDecl(true, f) g.Printf("\n") } - if cls.HasSuper() { + if _, ok := g.supers[cls.Name]; ok { g.Printf("Super() %s\n", goClsName(cls.Name)) } if cls.Throwable { diff --git a/bind/genjava.go b/bind/genjava.go index 780eeb6..bcd0a4c 100644 --- a/bind/genjava.go +++ b/bind/genjava.go @@ -228,21 +228,18 @@ func (g *JavaGen) genStruct(s structInfo) { v := params.At(0) if v.Name() == "this" { t := v.Type() - if isJavaType(t) { - clsName := classNameFor(t) - cls := g.clsMap[clsName] - found := false - for _, sup := range jinf.supers { - if cls == sup { - found = true - break + if t, ok := t.(*types.Named); ok { + obj := t.Obj() + pkg := obj.Pkg() + if pkgFirstElem(pkg) == "Java" { + clsName := classNameFor(t) + exp := g.javaPkgName(g.Pkg) + "." + s.obj.Name() + if clsName != exp { + g.errorf("the type %s of the `this` argument to method %s.%s is not %s", clsName, n, m.Name(), exp) + continue } + hasThis = true } - if !found { - g.errorf("the type %s of the `this` argument to method %s.%s is not a super class to %s", cls.Name, n, m.Name(), n) - continue - } - hasThis = true } } } diff --git a/bind/testdata/classes.go b/bind/testdata/classes.go index 696507e..8e531c0 100644 --- a/bind/testdata/classes.go +++ b/bind/testdata/classes.go @@ -5,6 +5,7 @@ package java import ( + gopkg "Java/go/java" "Java/java/io" "Java/java/lang" "Java/java/util/Spliterators" @@ -15,7 +16,7 @@ type Runnable struct { lang.Runnable } -func (r *Runnable) Run(this lang.Runnable) { +func (r *Runnable) Run(this gopkg.Runnable) { } type InputStream struct { diff --git a/bind/testdata/classes.go.golden b/bind/testdata/classes.go.golden index 2875ff7..fc10f31 100644 --- a/bind/testdata/classes.go.golden +++ b/bind/testdata/classes.go.golden @@ -11,7 +11,6 @@ type Java_lang_Runnable interface { type Java_io_InputStream interface { Read() (int32, error) - Super() Java_io_InputStream } type Java_util_concurrent_Future interface { @@ -20,16 +19,34 @@ type Java_util_concurrent_Future interface { } type Java_lang_Object interface { - Super() Java_lang_Object } type Java_util_concurrent_TimeUnit interface { - Super() Java_util_concurrent_TimeUnit } type Java_util_Spliterators interface { } +type Go_java_Future interface { + Get() (Java_lang_Object, error) + Get2(a0 int64, a1 Java_util_concurrent_TimeUnit) (Java_lang_Object, error) + Super() Go_java_Future +} + +type Go_java_InputStream interface { + Read() (int32, error) + Super() Go_java_InputStream +} + +type Go_java_Object interface { + Super() Go_java_Object +} + +type Go_java_Runnable interface { + Run() + Super() Go_java_Runnable +} + // File is generated by gobind. Do not edit. package gomobile_bind @@ -53,6 +70,10 @@ import "Java/java/util/concurrent/Future" import "Java/java/lang/Object" import "Java/java/util/concurrent/TimeUnit" import "Java/java/util/Spliterators" +import "Java/go/java/Future" +import "Java/go/java/InputStream" +import "Java/go/java/Object" +import "Java/go/java/Runnable" import "unsafe" import "reflect" @@ -75,6 +96,10 @@ func initClasses() { init_java_lang_Object() init_java_util_concurrent_TimeUnit() init_java_util_Spliterators() + init_go_java_Future() + init_go_java_InputStream() + init_go_java_Object() + init_go_java_Runnable() } var class_java_lang_Runnable C.jclass @@ -156,27 +181,6 @@ func (p *proxy_class_java_io_InputStream) Read() (int32, error) { return _res, _exc } -func (p *proxy_class_java_io_InputStream) Super() Java.Java_io_InputStream { - return &super_java_io_InputStream{p} -} - -type super_java_io_InputStream struct {*proxy_class_java_io_InputStream} - -func (p *super_java_io_InputStream) Read() (int32, error) { - res := C.csuper_java_io_InputStream_read__(C.jint(p.Bind_proxy_refnum__())) - _res := int32(res.res) - var _exc error - _exc_ref := _seq.FromRefNum(int32(res.exc)) - if _exc_ref != nil { - if res.exc < 0 { // go object - _exc = _exc_ref.Get().(error) - } else { // foreign object - _exc = (*proxy_error)(_exc_ref) - } - } - return _res, _exc -} - var class_java_util_concurrent_Future C.jclass func init_java_util_concurrent_Future() { @@ -278,12 +282,6 @@ type proxy_class_java_lang_Object _seq.Ref func (p *proxy_class_java_lang_Object) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } -func (p *proxy_class_java_lang_Object) Super() Java.Java_lang_Object { - return &super_java_lang_Object{p} -} - -type super_java_lang_Object struct {*proxy_class_java_lang_Object} - var class_java_util_concurrent_TimeUnit C.jclass func init_java_util_concurrent_TimeUnit() { @@ -309,12 +307,6 @@ type proxy_class_java_util_concurrent_TimeUnit _seq.Ref func (p *proxy_class_java_util_concurrent_TimeUnit) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } -func (p *proxy_class_java_util_concurrent_TimeUnit) Super() Java.Java_util_concurrent_TimeUnit { - return &super_java_util_concurrent_TimeUnit{p} -} - -type super_java_util_concurrent_TimeUnit struct {*proxy_class_java_util_concurrent_TimeUnit} - var class_java_util_Spliterators C.jclass func init_java_util_Spliterators() { @@ -376,6 +368,290 @@ type proxy_class_java_util_Spliterators _seq.Ref func (p *proxy_class_java_util_Spliterators) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } +var class_go_java_Future C.jclass + +func init_go_java_Future() { + cls := C.CString("go/java/Future") + clazz := C.go_seq_find_class(cls) + C.free(unsafe.Pointer(cls)) + if clazz == nil { + return + } + class_go_java_Future = clazz + Future.Cast = func(v interface{}) Java.Go_java_Future { + t := reflect.TypeOf((*proxy_class_go_java_Future)(nil)) + cv := reflect.ValueOf(v).Convert(t).Interface().(*proxy_class_go_java_Future) + ref := C.jint(_seq.ToRefNum(cv)) + if C.go_seq_isinstanceof(ref, class_go_java_Future) != 1 { + panic(fmt.Errorf("%T is not an instance of %s", v, "go.java.Future")) + } + return cv + } +} + +type proxy_class_go_java_Future _seq.Ref + +func (p *proxy_class_go_java_Future) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } + +func (p *proxy_class_go_java_Future) Get() (Java.Java_lang_Object, error) { + res := C.cproxy_go_java_Future_get__(C.jint(p.Bind_proxy_refnum__())) + var _res Java.Java_lang_Object + _res_ref := _seq.FromRefNum(int32(res.res)) + if _res_ref != nil { + if res.res < 0 { // go object + _res = _res_ref.Get().(Java.Java_lang_Object) + } else { // foreign object + _res = (*proxy_class_java_lang_Object)(_res_ref) + } + } + var _exc error + _exc_ref := _seq.FromRefNum(int32(res.exc)) + if _exc_ref != nil { + if res.exc < 0 { // go object + _exc = _exc_ref.Get().(error) + } else { // foreign object + _exc = (*proxy_error)(_exc_ref) + } + } + return _res, _exc +} + +func (p *proxy_class_go_java_Future) Get2(a0 int64, a1 Java.Java_util_concurrent_TimeUnit) (Java.Java_lang_Object, error) { + _a0 := C.jlong(a0) + var _a1 C.jint = _seq.NullRefNum + if a1 != nil { + _a1 = C.jint(_seq.ToRefNum(a1)) + } + res := C.cproxy_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2(C.jint(p.Bind_proxy_refnum__()), _a0, _a1) + var _res Java.Java_lang_Object + _res_ref := _seq.FromRefNum(int32(res.res)) + if _res_ref != nil { + if res.res < 0 { // go object + _res = _res_ref.Get().(Java.Java_lang_Object) + } else { // foreign object + _res = (*proxy_class_java_lang_Object)(_res_ref) + } + } + var _exc error + _exc_ref := _seq.FromRefNum(int32(res.exc)) + if _exc_ref != nil { + if res.exc < 0 { // go object + _exc = _exc_ref.Get().(error) + } else { // foreign object + _exc = (*proxy_error)(_exc_ref) + } + } + return _res, _exc +} + +func (p *proxy_class_go_java_Future) Super() Java.Go_java_Future { + return &super_go_java_Future{p} +} + +type super_go_java_Future struct {*proxy_class_go_java_Future} + +func (p *super_go_java_Future) Get() (Java.Java_lang_Object, error) { + res := C.csuper_go_java_Future_get__(C.jint(p.Bind_proxy_refnum__())) + var _res Java.Java_lang_Object + _res_ref := _seq.FromRefNum(int32(res.res)) + if _res_ref != nil { + if res.res < 0 { // go object + _res = _res_ref.Get().(Java.Java_lang_Object) + } else { // foreign object + _res = (*proxy_class_java_lang_Object)(_res_ref) + } + } + var _exc error + _exc_ref := _seq.FromRefNum(int32(res.exc)) + if _exc_ref != nil { + if res.exc < 0 { // go object + _exc = _exc_ref.Get().(error) + } else { // foreign object + _exc = (*proxy_error)(_exc_ref) + } + } + return _res, _exc +} + +func (p *super_go_java_Future) Get2(a0 int64, a1 Java.Java_util_concurrent_TimeUnit) (Java.Java_lang_Object, error) { + _a0 := C.jlong(a0) + var _a1 C.jint = _seq.NullRefNum + if a1 != nil { + _a1 = C.jint(_seq.ToRefNum(a1)) + } + res := C.csuper_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2(C.jint(p.Bind_proxy_refnum__()), _a0, _a1) + var _res Java.Java_lang_Object + _res_ref := _seq.FromRefNum(int32(res.res)) + if _res_ref != nil { + if res.res < 0 { // go object + _res = _res_ref.Get().(Java.Java_lang_Object) + } else { // foreign object + _res = (*proxy_class_java_lang_Object)(_res_ref) + } + } + var _exc error + _exc_ref := _seq.FromRefNum(int32(res.exc)) + if _exc_ref != nil { + if res.exc < 0 { // go object + _exc = _exc_ref.Get().(error) + } else { // foreign object + _exc = (*proxy_error)(_exc_ref) + } + } + return _res, _exc +} + +var class_go_java_InputStream C.jclass + +func init_go_java_InputStream() { + cls := C.CString("go/java/InputStream") + clazz := C.go_seq_find_class(cls) + C.free(unsafe.Pointer(cls)) + if clazz == nil { + return + } + class_go_java_InputStream = clazz + InputStream.Cast = func(v interface{}) Java.Go_java_InputStream { + t := reflect.TypeOf((*proxy_class_go_java_InputStream)(nil)) + cv := reflect.ValueOf(v).Convert(t).Interface().(*proxy_class_go_java_InputStream) + ref := C.jint(_seq.ToRefNum(cv)) + if C.go_seq_isinstanceof(ref, class_go_java_InputStream) != 1 { + panic(fmt.Errorf("%T is not an instance of %s", v, "go.java.InputStream")) + } + return cv + } +} + +type proxy_class_go_java_InputStream _seq.Ref + +func (p *proxy_class_go_java_InputStream) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } + +func (p *proxy_class_go_java_InputStream) Read() (int32, error) { + res := C.cproxy_go_java_InputStream_read__(C.jint(p.Bind_proxy_refnum__())) + _res := int32(res.res) + var _exc error + _exc_ref := _seq.FromRefNum(int32(res.exc)) + if _exc_ref != nil { + if res.exc < 0 { // go object + _exc = _exc_ref.Get().(error) + } else { // foreign object + _exc = (*proxy_error)(_exc_ref) + } + } + return _res, _exc +} + +func (p *proxy_class_go_java_InputStream) Super() Java.Go_java_InputStream { + return &super_go_java_InputStream{p} +} + +type super_go_java_InputStream struct {*proxy_class_go_java_InputStream} + +func (p *super_go_java_InputStream) Read() (int32, error) { + res := C.csuper_go_java_InputStream_read__(C.jint(p.Bind_proxy_refnum__())) + _res := int32(res.res) + var _exc error + _exc_ref := _seq.FromRefNum(int32(res.exc)) + if _exc_ref != nil { + if res.exc < 0 { // go object + _exc = _exc_ref.Get().(error) + } else { // foreign object + _exc = (*proxy_error)(_exc_ref) + } + } + return _res, _exc +} + +var class_go_java_Object C.jclass + +func init_go_java_Object() { + cls := C.CString("go/java/Object") + clazz := C.go_seq_find_class(cls) + C.free(unsafe.Pointer(cls)) + if clazz == nil { + return + } + class_go_java_Object = clazz + Object.Cast = func(v interface{}) Java.Go_java_Object { + t := reflect.TypeOf((*proxy_class_go_java_Object)(nil)) + cv := reflect.ValueOf(v).Convert(t).Interface().(*proxy_class_go_java_Object) + ref := C.jint(_seq.ToRefNum(cv)) + if C.go_seq_isinstanceof(ref, class_go_java_Object) != 1 { + panic(fmt.Errorf("%T is not an instance of %s", v, "go.java.Object")) + } + return cv + } +} + +type proxy_class_go_java_Object _seq.Ref + +func (p *proxy_class_go_java_Object) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } + +func (p *proxy_class_go_java_Object) Super() Java.Go_java_Object { + return &super_go_java_Object{p} +} + +type super_go_java_Object struct {*proxy_class_go_java_Object} + +var class_go_java_Runnable C.jclass + +func init_go_java_Runnable() { + cls := C.CString("go/java/Runnable") + clazz := C.go_seq_find_class(cls) + C.free(unsafe.Pointer(cls)) + if clazz == nil { + return + } + class_go_java_Runnable = clazz + Runnable.Cast = func(v interface{}) Java.Go_java_Runnable { + t := reflect.TypeOf((*proxy_class_go_java_Runnable)(nil)) + cv := reflect.ValueOf(v).Convert(t).Interface().(*proxy_class_go_java_Runnable) + ref := C.jint(_seq.ToRefNum(cv)) + if C.go_seq_isinstanceof(ref, class_go_java_Runnable) != 1 { + panic(fmt.Errorf("%T is not an instance of %s", v, "go.java.Runnable")) + } + return cv + } +} + +type proxy_class_go_java_Runnable _seq.Ref + +func (p *proxy_class_go_java_Runnable) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } + +func (p *proxy_class_go_java_Runnable) Run() { + res := C.cproxy_go_java_Runnable_run(C.jint(p.Bind_proxy_refnum__())) + var _exc error + _exc_ref := _seq.FromRefNum(int32(res)) + if _exc_ref != nil { + if res < 0 { // go object + _exc = _exc_ref.Get().(error) + } else { // foreign object + _exc = (*proxy_error)(_exc_ref) + } + } + if (_exc != nil) { panic(_exc) } +} + +func (p *proxy_class_go_java_Runnable) Super() Java.Go_java_Runnable { + return &super_go_java_Runnable{p} +} + +type super_go_java_Runnable struct {*proxy_class_go_java_Runnable} + +func (p *super_go_java_Runnable) Run() { + res := C.csuper_go_java_Runnable_run(C.jint(p.Bind_proxy_refnum__())) + var _exc error + _exc_ref := _seq.FromRefNum(int32(res)) + if _exc_ref != nil { + if res < 0 { // go object + _exc = _exc_ref.Get().(error) + } else { // foreign object + _exc = (*proxy_error)(_exc_ref) + } + } + if (_exc != nil) { panic(_exc) } +} + // Package gomobile_bind is an autogenerated binder stub for package java. // gobind -lang=go classes // @@ -392,6 +668,7 @@ package gomobile_bind import "C" import ( + java_1 "Java/go/java" "Java/java/io" "Java/java/lang" "Java/java/util/concurrent" @@ -572,13 +849,13 @@ func proxyjava_Runnable_Runnable_Get(refnum C.int32_t) C.int32_t { func proxyjava_Runnable_Run(refnum C.int32_t, param_this C.int32_t) { ref := _seq.FromRefNum(int32(refnum)) v := ref.Get().(*java.Runnable) - var _param_this lang.Runnable + var _param_this java_1.Runnable _param_this_ref := _seq.FromRefNum(int32(param_this)) if _param_this_ref != nil { if param_this < 0 { // go object - _param_this = _param_this_ref.Get().(lang.Runnable) + _param_this = _param_this_ref.Get().(java_1.Runnable) } else { // foreign object - _param_this = (*proxy_class_java_lang_Runnable)(_param_this_ref) + _param_this = (*proxy_class_go_java_Runnable)(_param_this_ref) } } v.Run(_param_this) diff --git a/bind/testdata/classes.java.c.golden b/bind/testdata/classes.java.c.golden index 013041d..2e7f7d8 100644 --- a/bind/testdata/classes.java.c.golden +++ b/bind/testdata/classes.java.c.golden @@ -29,9 +29,25 @@ ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024O } static jclass class_java_util_Spliterators; +static jclass class_go_java_Future; +static jclass sclass_go_java_Future; +static jmethodID m_go_java_Future_get__; +static jmethodID sm_go_java_Future_get__; +static jmethodID m_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2; +static jmethodID sm_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2; +static jclass class_go_java_InputStream; +static jclass sclass_go_java_InputStream; +static jmethodID m_go_java_InputStream_read__; +static jmethodID sm_go_java_InputStream_read__; +static jclass class_go_java_Object; +static jclass sclass_go_java_Object; +static jclass class_go_java_Runnable; +static jclass sclass_go_java_Runnable; +static jmethodID m_go_java_Runnable_run; +static jmethodID sm_go_java_Runnable_run; void init_proxies() { - JNIEnv *env = go_seq_push_local_frame(6); + JNIEnv *env = go_seq_push_local_frame(10); jclass clazz; clazz = (*env)->FindClass(env, "java/lang/Runnable"); class_java_lang_Runnable = (*env)->NewGlobalRef(env, clazz); @@ -49,6 +65,30 @@ void init_proxies() { class_java_util_concurrent_TimeUnit = (*env)->NewGlobalRef(env, clazz); clazz = (*env)->FindClass(env, "java/util/Spliterators"); class_java_util_Spliterators = (*env)->NewGlobalRef(env, clazz); + clazz = (*env)->FindClass(env, "go/java/Future"); + class_go_java_Future = (*env)->NewGlobalRef(env, clazz); + sclass_go_java_Future = (*env)->GetSuperclass(env, clazz); + sclass_go_java_Future = (*env)->NewGlobalRef(env, sclass_go_java_Future); + m_go_java_Future_get__ = go_seq_get_method_id(clazz, "get", "()Ljava/lang/Object;"); + sm_go_java_Future_get__ = go_seq_get_method_id(sclass_go_java_Future, "get", "()Ljava/lang/Object;"); + m_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2 = go_seq_get_method_id(clazz, "get", "(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;"); + sm_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2 = go_seq_get_method_id(sclass_go_java_Future, "get", "(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;"); + clazz = (*env)->FindClass(env, "go/java/InputStream"); + class_go_java_InputStream = (*env)->NewGlobalRef(env, clazz); + sclass_go_java_InputStream = (*env)->GetSuperclass(env, clazz); + sclass_go_java_InputStream = (*env)->NewGlobalRef(env, sclass_go_java_InputStream); + m_go_java_InputStream_read__ = go_seq_get_method_id(clazz, "read", "()I"); + sm_go_java_InputStream_read__ = go_seq_get_method_id(sclass_go_java_InputStream, "read", "()I"); + clazz = (*env)->FindClass(env, "go/java/Object"); + class_go_java_Object = (*env)->NewGlobalRef(env, clazz); + sclass_go_java_Object = (*env)->GetSuperclass(env, clazz); + sclass_go_java_Object = (*env)->NewGlobalRef(env, sclass_go_java_Object); + clazz = (*env)->FindClass(env, "go/java/Runnable"); + class_go_java_Runnable = (*env)->NewGlobalRef(env, clazz); + sclass_go_java_Runnable = (*env)->GetSuperclass(env, clazz); + sclass_go_java_Runnable = (*env)->NewGlobalRef(env, sclass_go_java_Runnable); + m_go_java_Runnable_run = go_seq_get_method_id(clazz, "run", "()V"); + sm_go_java_Runnable_run = go_seq_get_method_id(sclass_go_java_Runnable, "run", "()V"); go_seq_pop_local_frame(env); } @@ -79,22 +119,6 @@ ret_jint cproxy_java_io_InputStream_read__(jint this) { return __res; } -ret_jint csuper_java_io_InputStream_read__(jint this) { - JNIEnv *env = go_seq_push_local_frame(1); - // Must be a Java object - jobject _this = go_seq_from_refnum(env, this, NULL, NULL); - jint res = (*env)->CallNonvirtualIntMethod(env, _this, class_java_io_InputStream, m_java_io_InputStream_read__); - jobject _exc = go_seq_get_exception(env); - int32_t _exc_ref = go_seq_to_refnum(env, _exc); - if (_exc != NULL) { - res = 0; - } - jint _res = res; - go_seq_pop_local_frame(env); - ret_jint __res = {_res, _exc_ref}; - return __res; -} - ret_jint cproxy_java_util_concurrent_Future_get__(jint this) { JNIEnv *env = go_seq_push_local_frame(1); // Must be a Java object @@ -129,6 +153,128 @@ ret_jint cproxy_java_util_concurrent_Future_get__JLjava_util_concurrent_TimeUnit return __res; } +ret_jint cproxy_go_java_Future_get__(jint this) { + JNIEnv *env = go_seq_push_local_frame(1); + // Must be a Java object + jobject _this = go_seq_from_refnum(env, this, NULL, NULL); + jobject res = (*env)->CallObjectMethod(env, _this, m_go_java_Future_get__); + jobject _exc = go_seq_get_exception(env); + int32_t _exc_ref = go_seq_to_refnum(env, _exc); + if (_exc != NULL) { + res = NULL; + } + jint _res = go_seq_to_refnum(env, res); + go_seq_pop_local_frame(env); + ret_jint __res = {_res, _exc_ref}; + return __res; +} + +ret_jint csuper_go_java_Future_get__(jint this) { + JNIEnv *env = go_seq_push_local_frame(1); + // Must be a Java object + jobject _this = go_seq_from_refnum(env, this, NULL, NULL); + jobject res = (*env)->CallNonvirtualObjectMethod(env, _this, sclass_go_java_Future, sm_go_java_Future_get__); + jobject _exc = go_seq_get_exception(env); + int32_t _exc_ref = go_seq_to_refnum(env, _exc); + if (_exc != NULL) { + res = NULL; + } + jint _res = go_seq_to_refnum(env, res); + go_seq_pop_local_frame(env); + ret_jint __res = {_res, _exc_ref}; + return __res; +} + +ret_jint cproxy_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1) { + JNIEnv *env = go_seq_push_local_frame(3); + // Must be a Java object + jobject _this = go_seq_from_refnum(env, this, NULL, NULL); + jlong _a0 = a0; + jobject _a1 = go_seq_from_refnum(env, a1, NULL, NULL); + jobject res = (*env)->CallObjectMethod(env, _this, m_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2, _a0, _a1); + jobject _exc = go_seq_get_exception(env); + int32_t _exc_ref = go_seq_to_refnum(env, _exc); + if (_exc != NULL) { + res = NULL; + } + jint _res = go_seq_to_refnum(env, res); + go_seq_pop_local_frame(env); + ret_jint __res = {_res, _exc_ref}; + return __res; +} + +ret_jint csuper_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1) { + JNIEnv *env = go_seq_push_local_frame(3); + // Must be a Java object + jobject _this = go_seq_from_refnum(env, this, NULL, NULL); + jlong _a0 = a0; + jobject _a1 = go_seq_from_refnum(env, a1, NULL, NULL); + jobject res = (*env)->CallNonvirtualObjectMethod(env, _this, sclass_go_java_Future, sm_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2, _a0, _a1); + jobject _exc = go_seq_get_exception(env); + int32_t _exc_ref = go_seq_to_refnum(env, _exc); + if (_exc != NULL) { + res = NULL; + } + jint _res = go_seq_to_refnum(env, res); + go_seq_pop_local_frame(env); + ret_jint __res = {_res, _exc_ref}; + return __res; +} + +ret_jint cproxy_go_java_InputStream_read__(jint this) { + JNIEnv *env = go_seq_push_local_frame(1); + // Must be a Java object + jobject _this = go_seq_from_refnum(env, this, NULL, NULL); + jint res = (*env)->CallIntMethod(env, _this, m_go_java_InputStream_read__); + jobject _exc = go_seq_get_exception(env); + int32_t _exc_ref = go_seq_to_refnum(env, _exc); + if (_exc != NULL) { + res = 0; + } + jint _res = res; + go_seq_pop_local_frame(env); + ret_jint __res = {_res, _exc_ref}; + return __res; +} + +ret_jint csuper_go_java_InputStream_read__(jint this) { + JNIEnv *env = go_seq_push_local_frame(1); + // Must be a Java object + jobject _this = go_seq_from_refnum(env, this, NULL, NULL); + jint res = (*env)->CallNonvirtualIntMethod(env, _this, sclass_go_java_InputStream, sm_go_java_InputStream_read__); + jobject _exc = go_seq_get_exception(env); + int32_t _exc_ref = go_seq_to_refnum(env, _exc); + if (_exc != NULL) { + res = 0; + } + jint _res = res; + go_seq_pop_local_frame(env); + ret_jint __res = {_res, _exc_ref}; + return __res; +} + +jint cproxy_go_java_Runnable_run(jint this) { + JNIEnv *env = go_seq_push_local_frame(1); + // Must be a Java object + jobject _this = go_seq_from_refnum(env, this, NULL, NULL); + (*env)->CallVoidMethod(env, _this, m_go_java_Runnable_run); + jobject _exc = go_seq_get_exception(env); + int32_t _exc_ref = go_seq_to_refnum(env, _exc); + go_seq_pop_local_frame(env); + return _exc_ref; +} + +jint csuper_go_java_Runnable_run(jint this) { + JNIEnv *env = go_seq_push_local_frame(1); + // Must be a Java object + jobject _this = go_seq_from_refnum(env, this, NULL, NULL); + (*env)->CallNonvirtualVoidMethod(env, _this, sclass_go_java_Runnable, sm_go_java_Runnable_run); + jobject _exc = go_seq_get_exception(env); + int32_t _exc_ref = go_seq_to_refnum(env, _exc); + go_seq_pop_local_frame(env); + return _exc_ref; +} + // JNI functions for the Go <=> Java bridge. // gobind -lang=java classes // diff --git a/bind/testdata/classes.java.h.golden b/bind/testdata/classes.java.h.golden index 173d7c2..a110ec3 100644 --- a/bind/testdata/classes.java.h.golden +++ b/bind/testdata/classes.java.h.golden @@ -48,9 +48,16 @@ typedef struct ret_nbyteslice { extern jint cproxy_java_lang_Runnable_run(jint this); extern ret_jint cproxy_java_io_InputStream_read__(jint this); -extern ret_jint csuper_java_io_InputStream_read__(jint this); extern ret_jint cproxy_java_util_concurrent_Future_get__(jint this); extern ret_jint cproxy_java_util_concurrent_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1); +extern ret_jint cproxy_go_java_Future_get__(jint this); +extern ret_jint csuper_go_java_Future_get__(jint this); +extern ret_jint cproxy_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1); +extern ret_jint csuper_go_java_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1); +extern ret_jint cproxy_go_java_InputStream_read__(jint this); +extern ret_jint csuper_go_java_InputStream_read__(jint this); +extern jint cproxy_go_java_Runnable_run(jint this); +extern jint csuper_go_java_Runnable_run(jint this); extern ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2(jclass clazz, jmethodID m, jint a0); // JNI function headers for the Go <=> Java bridge. // gobind -lang=java classes diff --git a/bind/testdata/java.go.golden b/bind/testdata/java.go.golden index 0ba36a4..d40fa3f 100644 --- a/bind/testdata/java.go.golden +++ b/bind/testdata/java.go.golden @@ -9,7 +9,6 @@ type Java_lang_Float interface { } type Java_lang_Object interface { - Super() Java_lang_Object } type Java_lang_Runnable interface { @@ -19,7 +18,6 @@ type Java_lang_Character interface { } type Java_lang_Character_Subset interface { - Super() Java_lang_Character_Subset } // File is generated by gobind. Do not edit. @@ -117,12 +115,6 @@ type proxy_class_java_lang_Object _seq.Ref func (p *proxy_class_java_lang_Object) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } -func (p *proxy_class_java_lang_Object) Super() Java.Java_lang_Object { - return &super_java_lang_Object{p} -} - -type super_java_lang_Object struct {*proxy_class_java_lang_Object} - var class_java_lang_Runnable C.jclass func init_java_lang_Runnable() { @@ -198,12 +190,6 @@ type proxy_class_java_lang_Character_Subset _seq.Ref func (p *proxy_class_java_lang_Character_Subset) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } -func (p *proxy_class_java_lang_Character_Subset) Super() Java.Java_lang_Character_Subset { - return &super_java_lang_Character_Subset{p} -} - -type super_java_lang_Character_Subset struct {*proxy_class_java_lang_Character_Subset} - // Package gomobile_bind is an autogenerated binder stub for package java. // gobind -lang=go java // @@ -230,21 +216,14 @@ type proxyjava_F _seq.Ref func (p *proxyjava_F) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } -// skipped method O.Super with unsupported parameter or return types - type proxyjava_O _seq.Ref func (p *proxyjava_O) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } -// skipped method O.Super with unsupported parameter or result types type proxyjava_R _seq.Ref func (p *proxyjava_R) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } -// skipped method S.Super with unsupported parameter or return types - type proxyjava_S _seq.Ref func (p *proxyjava_S) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() } - -// skipped method S.Super with unsupported parameter or result types diff --git a/bind/testdata/java.java.c.golden b/bind/testdata/java.java.c.golden index 814478f..26b7f24 100644 --- a/bind/testdata/java.java.c.golden +++ b/bind/testdata/java.java.c.golden @@ -41,14 +41,10 @@ jclass proxy_class_java_F; jmethodID proxy_class_java_F_cons; jclass proxy_class_java_O; jmethodID proxy_class_java_O_cons; -// skipped method O.Super with unsupported parameter or return types - jclass proxy_class_java_R; jmethodID proxy_class_java_R_cons; jclass proxy_class_java_S; jmethodID proxy_class_java_S_cons; -// skipped method S.Super with unsupported parameter or return types - JNIEXPORT void JNICALL Java_go_java_Java__1init(JNIEnv *env, jclass _unused) { @@ -62,8 +58,6 @@ Java_go_java_Java__1init(JNIEnv *env, jclass _unused) { proxy_class_java_O = (*env)->NewGlobalRef(env, clazz); proxy_class_java_O_cons = (*env)->GetMethodID(env, clazz, "", "(Lgo/Seq$Ref;)V"); clazz = (*env)->FindClass(env, "go/java/O"); - // skipped method O.Super with unsupported parameter or return types - clazz = (*env)->FindClass(env, "go/java/Java$proxyR"); proxy_class_java_R = (*env)->NewGlobalRef(env, clazz); @@ -74,16 +68,6 @@ Java_go_java_Java__1init(JNIEnv *env, jclass _unused) { proxy_class_java_S = (*env)->NewGlobalRef(env, clazz); proxy_class_java_S_cons = (*env)->GetMethodID(env, clazz, "", "(Lgo/Seq$Ref;)V"); clazz = (*env)->FindClass(env, "go/java/S"); - // skipped method S.Super with unsupported parameter or return types - } -// skipped function O.Super with unsupported parameter or return types - -// skipped method O with unsupported parameter or return types - -// skipped function S.Super with unsupported parameter or return types - -// skipped method S with unsupported parameter or return types - diff --git a/bind/testdata/java.java.golden b/bind/testdata/java.java.golden index 74d9694..7a01da8 100644 --- a/bind/testdata/java.java.golden +++ b/bind/testdata/java.java.golden @@ -18,9 +18,7 @@ package go.java; import go.Seq; -public interface O extends F, R { - // skipped method O.Super with unsupported parameter or return types - +public interface O { } @@ -44,9 +42,7 @@ package go.java; import go.Seq; -public interface S extends F, R { - // skipped method S.Super with unsupported parameter or return types - +public interface S { } @@ -94,8 +90,6 @@ public abstract class Java { proxyO(Seq.Ref ref) { this.ref = ref; } - // skipped method O.Super with unsupported parameter or return types - } private static final class proxyR implements Seq.Proxy, R { private final Seq.Ref ref; @@ -120,8 +114,6 @@ public abstract class Java { proxyS(Seq.Ref ref) { this.ref = ref; } - // skipped method S.Super with unsupported parameter or return types - } diff --git a/bind/testdata/java.java.h.golden b/bind/testdata/java.java.h.golden index 03bbe6f..a95fe25 100644 --- a/bind/testdata/java.java.h.golden +++ b/bind/testdata/java.java.h.golden @@ -62,14 +62,10 @@ extern jmethodID proxy_class_java_F_cons; extern jclass proxy_class_java_O; extern jmethodID proxy_class_java_O_cons; -// skipped method O.Super with unsupported parameter or return types - extern jclass proxy_class_java_R; extern jmethodID proxy_class_java_R_cons; extern jclass proxy_class_java_S; extern jmethodID proxy_class_java_S_cons; -// skipped method S.Super with unsupported parameter or return types - #endif diff --git a/bind/testpkg/javapkg/classes.go b/bind/testpkg/javapkg/classes.go index 7043c5f..4c79199 100644 --- a/bind/testpkg/javapkg/classes.go +++ b/bind/testpkg/javapkg/classes.go @@ -7,6 +7,7 @@ package javapkg import ( + gopkg "Java/go/javapkg" "Java/java/beans" "Java/java/io" "Java/java/io/IOException" @@ -34,14 +35,14 @@ type GoRunnable struct { Field string } -func (r *GoRunnable) ToString(this lang.Runnable) string { +func (r *GoRunnable) ToString(this gopkg.GoRunnable) string { return ToStringPrefix } -func (r *GoRunnable) Run(this lang.Runnable) { +func (r *GoRunnable) Run(this gopkg.GoRunnable) { } -func (r *GoRunnable) GetThis(this lang.Runnable) lang.Runnable { +func (r *GoRunnable) GetThis(this gopkg.GoRunnable) lang.Runnable { return this } @@ -86,7 +87,7 @@ type GoObject struct { this lang.Object } -func (o *GoObject) ToString(this lang.Object) string { +func (o *GoObject) ToString(this gopkg.GoObject) string { o.this = this return ToStringPrefix + this.Super().ToString() } @@ -171,7 +172,7 @@ type GoRand struct { util.Random } -func (_ *GoRand) Next(this util.Random, i int32) int32 { +func (_ *GoRand) Next(this gopkg.GoRand, i int32) int32 { return this.Super().Next(i) } diff --git a/cmd/gobind/gen.go b/cmd/gobind/gen.go index 8325b84..b8215d0 100644 --- a/cmd/gobind/gen.go +++ b/cmd/gobind/gen.go @@ -140,7 +140,7 @@ func genPkg(p *types.Package, allPkg []*types.Package, classes []*java.Class) { } } -func genJavaPackages(ctx *build.Context, dir string, classes []*java.Class) error { +func genJavaPackages(ctx *build.Context, dir string, classes []*java.Class, genNames []string) error { var buf bytes.Buffer cg := &bind.ClassGen{ Printer: &bind.Printer{ @@ -148,7 +148,7 @@ func genJavaPackages(ctx *build.Context, dir string, classes []*java.Class) erro Buf: &buf, }, } - cg.Init(classes) + cg.Init(classes, genNames) pkgBase := filepath.Join(dir, "src", "Java") if err := os.MkdirAll(pkgBase, 0700); err != nil { return err diff --git a/cmd/gobind/main.go b/cmd/gobind/main.go index ef6e808..86f02d3 100644 --- a/cmd/gobind/main.go +++ b/cmd/gobind/main.go @@ -60,7 +60,19 @@ func main() { log.Fatal(err) } if len(refs.Refs) > 0 { - classes, err = java.Import(*bootclasspath, *classpath, refs) + pref := *javaPkg + if pref == "" { + pref = "go" + } + if pref != "" { + pref = pref + "." + } + imp := &java.Importer{ + Bootclasspath: *bootclasspath, + Classpath: *classpath, + JavaPkgPrefix: pref, + } + classes, err = imp.Import(refs) if err != nil { log.Fatal(err) } @@ -70,7 +82,11 @@ func main() { log.Fatal(err) } defer os.RemoveAll(tmpGopath) - if err := genJavaPackages(ctx, tmpGopath, classes); err != nil { + var genNames []string + for _, emb := range refs.Embedders { + genNames = append(genNames, pref+emb.Pkg+"."+emb.Name) + } + if err := genJavaPackages(ctx, tmpGopath, classes, genNames); err != nil { log.Fatal(err) } gopath := ctx.GOPATH diff --git a/cmd/gomobile/bind.go b/cmd/gomobile/bind.go index a3202f7..9bef68a 100644 --- a/cmd/gomobile/bind.go +++ b/cmd/gomobile/bind.go @@ -391,7 +391,19 @@ func GenClasses(pkgs []*build.Package, srcDir, jpkgSrc string) ([]*java.Class, e if err != nil { return nil, err } - classes, err := java.Import(bClspath, bindClasspath, refs) + pref := bindJavaPkg + if pref == "" { + pref = "go" + } + if pref != "" { + pref = pref + "." + } + imp := &java.Importer{ + Bootclasspath: bClspath, + Classpath: bindClasspath, + JavaPkgPrefix: pref, + } + classes, err := imp.Import(refs) if err != nil { return nil, err } @@ -402,7 +414,11 @@ func GenClasses(pkgs []*build.Package, srcDir, jpkgSrc string) ([]*java.Class, e Buf: &buf, }, } - g.Init(classes) + var genNames []string + for _, emb := range refs.Embedders { + genNames = append(genNames, pref+emb.Pkg+"."+emb.Name) + } + g.Init(classes, genNames) for i, jpkg := range g.Packages() { pkgDir := filepath.Join(jpkgSrc, "src", "Java", jpkg) if err := os.MkdirAll(pkgDir, 0700); err != nil { diff --git a/example/reverse/reverse/reverse.go b/example/reverse/reverse/reverse.go index c4c3377..a07d834 100644 --- a/example/reverse/reverse/reverse.go +++ b/example/reverse/reverse/reverse.go @@ -9,6 +9,7 @@ import ( "Java/android/databinding/DataBindingUtil" "Java/android/os" "Java/android/support/v7/app" + gopkg "Java/go/reverse" rlayout "Java/go/reverse/R/layout" "Java/go/reverse/databinding/ActivityMainBinding" ) @@ -17,7 +18,7 @@ type MainActivity struct { app.AppCompatActivity } -func (a *MainActivity) OnCreate1(this app.AppCompatActivity, b os.Bundle) { +func (a *MainActivity) OnCreate1(this gopkg.MainActivity, b os.Bundle) { this.Super().OnCreate1(b) db := DataBindingUtil.SetContentView2(this, rlayout.Activity_main) mainBind := ActivityMainBinding.Cast(db) diff --git a/internal/importers/java/java.go b/internal/importers/java/java.go index a84a673..890ec46 100644 --- a/internal/importers/java/java.go +++ b/internal/importers/java/java.go @@ -93,10 +93,13 @@ type Type struct { type TypeKind int -type importer struct { - bootclspath string - clspath string - clsMap map[string]*Class +type Importer struct { + Bootclasspath string + Classpath string + // JavaPkgPrefix is java package name for generated classes. + JavaPkgPrefix string + + clsMap map[string]*Class } const ( @@ -148,11 +151,9 @@ func javapPath() (string, error) { // ... // // } -func Import(bootclasspath, classpath string, refs *importers.References) ([]*Class, error) { - imp := &importer{ - bootclspath: bootclasspath, - clspath: classpath, - clsMap: make(map[string]*Class), +func (j *Importer) Import(refs *importers.References) ([]*Class, error) { + if j.clsMap == nil { + j.clsMap = make(map[string]*Class) } clsSet := make(map[string]struct{}) var names []string @@ -166,19 +167,44 @@ func Import(bootclasspath, classpath string, refs *importers.References) ([]*Cla } } } - classes, err := imp.importClasses(names, true) + classes, err := j.importClasses(names, true) if err != nil { return nil, err } - for _, cls := range classes { - imp.fillAllMethods(cls) + // Embedders refer to every exported Go struct that will have its class + // generated. Allow Go code to reverse bind to those classes by synthesizing + // their class descriptors. + for _, emb := range refs.Embedders { + n := j.JavaPkgPrefix + emb.Pkg + "." + emb.Name + if _, exists := j.clsMap[n]; exists { + continue + } + cls := &Class{ + Name: n, + FindName: n, + JNIName: JNIMangle(n), + PkgName: emb.Name, + } + for _, ref := range emb.Refs { + jpkg := strings.Replace(ref.Pkg, "/", ".", -1) + super := jpkg + "." + ref.Name + if _, exists := j.clsMap[super]; !exists { + return nil, fmt.Errorf("class %q not found", super) + } + cls.Supers = append(cls.Supers, super) + } + classes = append(classes, cls) + j.clsMap[cls.Name] = cls } - imp.fillThrowables() for _, cls := range classes { - imp.mangleOverloads(cls.AllMethods) - imp.mangleOverloads(cls.Funcs) + j.fillAllMethods(cls) } - imp.filterReferences(classes, refs) + j.fillThrowables() + for _, cls := range classes { + j.mangleOverloads(cls.AllMethods) + j.mangleOverloads(cls.Funcs) + } + j.filterReferences(classes, refs) return classes, nil } @@ -211,10 +237,6 @@ func JNIMangle(s string) string { return string(m) } -func (c *Class) HasSuper() bool { - return !c.Final && !c.Interface -} - func (t *Type) Type() string { switch t.Kind { case Int: @@ -316,7 +338,7 @@ func (t *Type) JNICallType() string { } } -func (j *importer) filterReferences(classes []*Class, refs *importers.References) { +func (j *Importer) filterReferences(classes []*Class, refs *importers.References) { refFuncs := make(map[[2]string]struct{}) for _, ref := range refs.Refs { pkgName := strings.Replace(ref.Pkg, "/", ".", -1) @@ -351,16 +373,16 @@ func (j *importer) filterReferences(classes []*Class, refs *importers.References } } -func (j *importer) importClasses(names []string, allowMissingClasses bool) ([]*Class, error) { +func (j *Importer) importClasses(names []string, allowMissingClasses bool) ([]*Class, error) { if len(names) == 0 { return nil, nil } args := []string{"-J-Duser.language=en", "-s", "-protected", "-constants"} - if j.clspath != "" { - args = append(args, "-classpath", j.clspath) + if j.Classpath != "" { + args = append(args, "-classpath", j.Classpath) } - if j.bootclspath != "" { - args = append(args, "-bootclasspath", j.bootclspath) + if j.Bootclasspath != "" { + args = append(args, "-bootclasspath", j.Bootclasspath) } args = append(args, names...) javapPath, err := javapPath() @@ -411,7 +433,7 @@ func (j *importer) importClasses(names []string, allowMissingClasses bool) ([]*C return classes, nil } -func (j *importer) unknownSuperClasses(cls *Class, unk []string) []string { +func (j *Importer) unknownSuperClasses(cls *Class, unk []string) []string { loop: for _, n := range cls.Supers { if s, exists := j.clsMap[n]; exists { @@ -428,7 +450,7 @@ loop: return unk } -func (j *importer) scanClass(s *bufio.Scanner, name string) (*Class, error) { +func (j *Importer) scanClass(s *bufio.Scanner, name string) (*Class, error) { if !s.Scan() { return nil, fmt.Errorf("%s: missing javap header", name) } @@ -544,7 +566,7 @@ func (j *importer) scanClass(s *bufio.Scanner, name string) (*Class, error) { return cls, nil } -func (j *importer) scanClassDecl(name string, decl string) (*Class, error) { +func (j *Importer) scanClassDecl(name string, decl string) (*Class, error) { cls := &Class{ Name: name, } @@ -633,7 +655,7 @@ func (j *importer) scanClassDecl(name string, decl string) (*Class, error) { return nil, fmt.Errorf("missing ending { in class declaration: %q", decl) } -func (j *importer) scanVar(decl, desc string) (*Var, error) { +func (j *Importer) scanVar(decl, desc string) (*Var, error) { v := new(Var) const eq = " = " idx := strings.Index(decl, eq) @@ -664,7 +686,7 @@ func (j *importer) scanVar(decl, desc string) (*Var, error) { return v, nil } -func (j *importer) scanMethod(decl, desc string, parenIdx int) (*Func, error) { +func (j *Importer) scanMethod(decl, desc string, parenIdx int) (*Func, error) { // Member is a method f := new(Func) f.Desc = desc @@ -705,7 +727,7 @@ func (j *importer) scanMethod(decl, desc string, parenIdx int) (*Func, error) { return f, nil } -func (j *importer) fillThrowables() { +func (j *Importer) fillThrowables() { thrCls, ok := j.clsMap["java.lang.Throwable"] if !ok { // If Throwable isn't in the class map @@ -717,7 +739,7 @@ func (j *importer) fillThrowables() { } } -func (j *importer) fillThrowableFor(cls, thrCls *Class) { +func (j *Importer) fillThrowableFor(cls, thrCls *Class) { if cls.Interface || cls.Throwable { return } @@ -729,7 +751,7 @@ func (j *importer) fillThrowableFor(cls, thrCls *Class) { } } -func (j *importer) fillAllMethods(cls *Class) { +func (j *Importer) fillAllMethods(cls *Class) { if len(cls.AllMethods) > 0 { return } @@ -764,7 +786,7 @@ func (j *importer) fillAllMethods(cls *Class) { // mangleOverloads assigns unique names to overloaded Java functions by appending // the argument count. If multiple methods have the same name and argument count, // the method signature is appended in JNI mangled form. -func (j *importer) mangleOverloads(allFuncs []*Func) { +func (j *Importer) mangleOverloads(allFuncs []*Func) { overloads := make(map[string][]*Func) for _, f := range allFuncs { overloads[f.Name] = append(overloads[f.Name], f) @@ -795,7 +817,7 @@ func (j *importer) mangleOverloads(allFuncs []*Func) { } } -func (j *importer) parseJavaValue(v string) (string, bool) { +func (j *Importer) parseJavaValue(v string) (string, bool) { v = strings.TrimRight(v, "df") switch v { case "", "NaN", "Infinity", "-Infinity": @@ -810,7 +832,7 @@ func (j *importer) parseJavaValue(v string) (string, bool) { } } -func (j *importer) parseJavaType(desc string) (*Type, int, error) { +func (j *Importer) parseJavaType(desc string) (*Type, int, error) { t := new(Type) var n int if desc == "" { diff --git a/internal/importers/java/java_test.go b/internal/importers/java/java_test.go index 7cd4c86..c970a5a 100644 --- a/internal/importers/java/java_test.go +++ b/internal/importers/java/java_test.go @@ -43,7 +43,7 @@ func TestImport(t *testing.T) { for _, m := range test.methods { refs.Names[m.GoName] = struct{}{} } - classes, err := Import("", "", refs) + classes, err := (&Importer{}).Import(refs) if err != nil { t.Fatal(err) }