diff --git a/bind/gen.go b/bind/gen.go index b03277f..8a9889b 100644 --- a/bind/gen.go +++ b/bind/gen.go @@ -67,6 +67,8 @@ type generator struct { interfaces []interfaceInfo structs []structInfo otherNames []*types.TypeName + // allIntf contains interfaces from all bound packages. + allIntf []interfaceInfo } // pkgPrefix returns a prefix that disambiguates symbol names for binding @@ -117,6 +119,21 @@ func (g *generator) init() { if !hasExported { g.errorf("no exported names in the package %q", g.pkg.Path()) } + for _, p := range g.allPkg { + scope := p.Scope() + for _, name := range scope.Names() { + obj := scope.Lookup(name) + if !obj.Exported() { + continue + } + if obj, ok := obj.(*types.TypeName); ok { + named := obj.Type().(*types.Named) + if t, ok := named.Underlying().(*types.Interface); ok { + g.allIntf = append(g.allIntf, interfaceInfo{obj, t, makeIfaceSummary(t)}) + } + } + } + } } func (_ *generator) toCFlag(v bool) int { @@ -227,7 +244,7 @@ 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() { + if p == pkg { return true } } diff --git a/bind/genjava.go b/bind/genjava.go index d2af44a..cd66ac5 100644 --- a/bind/genjava.go +++ b/bind/genjava.go @@ -29,9 +29,13 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) { impls := []string{"go.Seq.Object"} pT := types.NewPointer(obj.Type()) - for _, iface := range g.interfaces { + for _, iface := range g.allIntf { if types.AssignableTo(pT, iface.obj.Type()) { - impls = append(impls, iface.obj.Name()) + n := iface.obj.Name() + if p := iface.obj.Pkg(); p != g.pkg { + n = fmt.Sprintf("%s.%s.%s", g.javaPkgName(p), className(p), n) + } + impls = append(impls, n) } } g.Printf("public static final class %s implements %s {\n", obj.Name(), strings.Join(impls, ", ")) @@ -45,7 +49,7 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) { for _, f := range fields { if t := f.Type(); !g.isSupported(t) { - g.Printf("// skipped field %s.%s with unsupported type: %T\n\n", f.Name(), t) + g.Printf("// skipped field %s.%s with unsupported type: %T\n\n", n, f.Name(), t) continue } g.Printf("public final native %s get%s();\n", g.javaType(f.Type()), f.Name()) @@ -70,7 +74,7 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) { g.Printf("%s that = (%s)o;\n", n, n) for _, f := range fields { if t := f.Type(); !g.isSupported(t) { - g.Printf("// skipped field %s.%s with unsupported type: %T\n\n", f.Name(), t) + g.Printf("// skipped field %s.%s with unsupported type: %T\n\n", n, f.Name(), t) continue } nf := f.Name() @@ -145,7 +149,19 @@ func (g *javaGen) genInterfaceStub(o *types.TypeName, m *types.Interface) { } func (g *javaGen) genInterface(iface interfaceInfo) { - g.Printf("public interface %s extends go.Seq.Object {\n", iface.obj.Name()) + exts := []string{"go.Seq.Object"} + numM := iface.t.NumMethods() + for _, other := range g.allIntf { + // Only extend interfaces with fewer methods to avoid circular references + if other.t.NumMethods() < numM && types.AssignableTo(iface.t, other.t) { + n := other.obj.Name() + if p := other.obj.Pkg(); p != g.pkg { + n = fmt.Sprintf("%s.%s.%s", g.javaPkgName(p), className(p), n) + } + exts = append(exts, n) + } + } + g.Printf("public interface %s extends %s {\n", iface.obj.Name(), strings.Join(exts, ", ")) g.Indent() methodSigErr := false diff --git a/bind/java/SeqTest.java b/bind/java/SeqTest.java index fa36f7d..bcd5929 100644 --- a/bind/java/SeqTest.java +++ b/bind/java/SeqTest.java @@ -496,6 +496,10 @@ public class SeqTest extends InstrumentationTestCase { fields.setS(s); Testpkg.WithImportedI(i); Testpkg.WithImportedS(s); + + Secondpkg.IF f = new AnI(); + f = Testpkg.New(); + Secondpkg.Ser ser = Testpkg.NewSer(); } public void testIDup() { diff --git a/bind/testdata/ignore.java.golden b/bind/testdata/ignore.java.golden index 05a615a..4ffbbb9 100644 --- a/bind/testdata/ignore.java.golden +++ b/bind/testdata/ignore.java.golden @@ -26,7 +26,7 @@ public abstract class Ignore { public final go.Seq.Ref ref() { return ref; } - // skipped field F.interface{} with unsupported type: %!T(MISSING) + // skipped field S.F with unsupported type: *types.Interface // skipped method S.Argument with unsupported parameter or return types @@ -37,7 +37,7 @@ public abstract class Ignore { return false; } S that = (S)o; - // skipped field F.interface{} with unsupported type: %!T(MISSING) + // skipped field S.F with unsupported type: *types.Interface return true; } diff --git a/bind/testdata/interfaces.go b/bind/testdata/interfaces.go index eebb091..0eaa99a 100644 --- a/bind/testdata/interfaces.go +++ b/bind/testdata/interfaces.go @@ -8,6 +8,15 @@ type I interface { Rand() int32 } +type SameI interface { + Rand() int32 +} + +type LargerI interface { + Rand() int32 + AnotherFunc() +} + func Add3(r I) int32 { return r.Rand() + r.Rand() + r.Rand() } diff --git a/bind/testdata/interfaces.go.golden b/bind/testdata/interfaces.go.golden index 4237e4f..c6fc0e3 100644 --- a/bind/testdata/interfaces.go.golden +++ b/bind/testdata/interfaces.go.golden @@ -108,6 +108,55 @@ func (p *proxyinterfaces_I3) F() interfaces.I1 { return _res } +//export proxyinterfaces_LargerI_AnotherFunc +func proxyinterfaces_LargerI_AnotherFunc(refnum C.int32_t) { + ref := _seq.FromRefNum(int32(refnum)) + v := ref.Get().(interfaces.LargerI) + v.AnotherFunc() +} + +//export proxyinterfaces_LargerI_Rand +func proxyinterfaces_LargerI_Rand(refnum C.int32_t) C.int32_t { + ref := _seq.FromRefNum(int32(refnum)) + v := ref.Get().(interfaces.LargerI) + res_0 := v.Rand() + _res_0 := C.int32_t(res_0) + return _res_0 +} + +type proxyinterfaces_LargerI _seq.Ref + +func (p *proxyinterfaces_LargerI) Bind_proxy_refnum__() int32 { return p.Bind_Num } + +func (p *proxyinterfaces_LargerI) AnotherFunc() { + C.cproxyinterfaces_LargerI_AnotherFunc(C.int32_t(p.Bind_Num)) +} + +func (p *proxyinterfaces_LargerI) Rand() int32 { + res := C.cproxyinterfaces_LargerI_Rand(C.int32_t(p.Bind_Num)) + _res := int32(res) + return _res +} + +//export proxyinterfaces_SameI_Rand +func proxyinterfaces_SameI_Rand(refnum C.int32_t) C.int32_t { + ref := _seq.FromRefNum(int32(refnum)) + v := ref.Get().(interfaces.SameI) + res_0 := v.Rand() + _res_0 := C.int32_t(res_0) + return _res_0 +} + +type proxyinterfaces_SameI _seq.Ref + +func (p *proxyinterfaces_SameI) Bind_proxy_refnum__() int32 { return p.Bind_Num } + +func (p *proxyinterfaces_SameI) Rand() int32 { + res := C.cproxyinterfaces_SameI_Rand(C.int32_t(p.Bind_Num)) + _res := int32(res) + return _res +} + //export proxyinterfaces_WithParam_HasParam func proxyinterfaces_WithParam_HasParam(refnum C.int32_t, param_p0 C.char) { ref := _seq.FromRefNum(int32(refnum)) diff --git a/bind/testdata/interfaces.java.c.golden b/bind/testdata/interfaces.java.c.golden index 655b440..b01109b 100644 --- a/bind/testdata/interfaces.java.c.golden +++ b/bind/testdata/interfaces.java.c.golden @@ -24,6 +24,13 @@ static jmethodID mid_I2_G; jclass proxy_class_interfaces_I3; jmethodID proxy_class_interfaces_I3_cons; static jmethodID mid_I3_F; +jclass proxy_class_interfaces_LargerI; +jmethodID proxy_class_interfaces_LargerI_cons; +static jmethodID mid_LargerI_AnotherFunc; +static jmethodID mid_LargerI_Rand; +jclass proxy_class_interfaces_SameI; +jmethodID proxy_class_interfaces_SameI_cons; +static jmethodID mid_SameI_Rand; jclass proxy_class_interfaces_WithParam; jmethodID proxy_class_interfaces_WithParam_cons; static jmethodID mid_WithParam_HasParam; @@ -61,6 +68,19 @@ Java_go_interfaces_Interfaces_init(JNIEnv *env, jclass _unused) { clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$I3"); mid_I3_F = (*env)->GetMethodID(env, clazz, "F", "()Lgo/interfaces/Interfaces$I1;"); + clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$LargerI$Proxy"); + proxy_class_interfaces_LargerI = (*env)->NewGlobalRef(env, clazz); + proxy_class_interfaces_LargerI_cons = (*env)->GetMethodID(env, clazz, "", "(Lgo/Seq$Ref;)V"); + clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$LargerI"); + mid_LargerI_AnotherFunc = (*env)->GetMethodID(env, clazz, "AnotherFunc", "()V"); + mid_LargerI_Rand = (*env)->GetMethodID(env, clazz, "Rand", "()I"); + + clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$SameI$Proxy"); + proxy_class_interfaces_SameI = (*env)->NewGlobalRef(env, clazz); + proxy_class_interfaces_SameI_cons = (*env)->GetMethodID(env, clazz, "", "(Lgo/Seq$Ref;)V"); + clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$SameI"); + mid_SameI_Rand = (*env)->GetMethodID(env, clazz, "Rand", "()I"); + clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$WithParam$Proxy"); proxy_class_interfaces_WithParam = (*env)->NewGlobalRef(env, clazz); proxy_class_interfaces_WithParam_cons = (*env)->GetMethodID(env, clazz, "", "(Lgo/Seq$Ref;)V"); @@ -170,6 +190,53 @@ int32_t cproxyinterfaces_I3_F(int32_t refnum) { return _res; } +JNIEXPORT void JNICALL +Java_go_interfaces_Interfaces_00024LargerI_00024Proxy_AnotherFunc(JNIEnv* env, jobject this) { + int32_t o = go_seq_to_refnum(env, this); + proxyinterfaces_LargerI_AnotherFunc(o); +} + +void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum) { + JNIEnv *env = go_seq_push_local_frame(10); + jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_LargerI, proxy_class_interfaces_LargerI_cons); + (*env)->CallVoidMethod(env, o, mid_LargerI_AnotherFunc); + go_seq_pop_local_frame(env); +} + +JNIEXPORT jint JNICALL +Java_go_interfaces_Interfaces_00024LargerI_00024Proxy_Rand(JNIEnv* env, jobject this) { + int32_t o = go_seq_to_refnum(env, this); + int32_t r0 = proxyinterfaces_LargerI_Rand(o); + jint _r0 = (jint)r0; + return _r0; +} + +int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum) { + JNIEnv *env = go_seq_push_local_frame(10); + jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_LargerI, proxy_class_interfaces_LargerI_cons); + jint res = (*env)->CallIntMethod(env, o, mid_LargerI_Rand); + int32_t _res = (int32_t)res; + go_seq_pop_local_frame(env); + return _res; +} + +JNIEXPORT jint JNICALL +Java_go_interfaces_Interfaces_00024SameI_00024Proxy_Rand(JNIEnv* env, jobject this) { + int32_t o = go_seq_to_refnum(env, this); + int32_t r0 = proxyinterfaces_SameI_Rand(o); + jint _r0 = (jint)r0; + return _r0; +} + +int32_t cproxyinterfaces_SameI_Rand(int32_t refnum) { + JNIEnv *env = go_seq_push_local_frame(10); + jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_SameI, proxy_class_interfaces_SameI_cons); + jint res = (*env)->CallIntMethod(env, o, mid_SameI_Rand); + int32_t _res = (int32_t)res; + go_seq_pop_local_frame(env); + return _res; +} + JNIEXPORT void JNICALL Java_go_interfaces_Interfaces_00024WithParam_00024Proxy_HasParam(JNIEnv* env, jobject this, jboolean p0) { int32_t o = go_seq_to_refnum(env, this); diff --git a/bind/testdata/interfaces.java.golden b/bind/testdata/interfaces.java.golden index 9e9b338..9dd7c19 100644 --- a/bind/testdata/interfaces.java.golden +++ b/bind/testdata/interfaces.java.golden @@ -114,6 +114,54 @@ public abstract class Interfaces { } } + public interface LargerI extends go.Seq.Object, I, SameI { + public void AnotherFunc(); + public int Rand(); + public static abstract class Stub implements LargerI { + private final go.Seq.Ref ref; + public Stub() { + ref = go.Seq.createRef(this); + } + + public final go.Seq.Ref ref() { return ref; } + + } + + static final class Proxy implements LargerI { + private go.Seq.Ref ref; + + Proxy(go.Seq.Ref ref) { this.ref = ref; } + + public final go.Seq.Ref ref() { return ref; } + + public native void AnotherFunc(); + public native int Rand(); + } + } + + public interface SameI extends go.Seq.Object { + public int Rand(); + public static abstract class Stub implements SameI { + private final go.Seq.Ref ref; + public Stub() { + ref = go.Seq.createRef(this); + } + + public final go.Seq.Ref ref() { return ref; } + + } + + static final class Proxy implements SameI { + private go.Seq.Ref ref; + + Proxy(go.Seq.Ref ref) { this.ref = ref; } + + public final go.Seq.Ref ref() { return ref; } + + public native int Rand(); + } + } + public interface WithParam extends go.Seq.Object { public void HasParam(boolean p0); public static abstract class Stub implements WithParam { diff --git a/bind/testdata/interfaces.java.h.golden b/bind/testdata/interfaces.java.h.golden index df496ea..a511de4 100644 --- a/bind/testdata/interfaces.java.h.golden +++ b/bind/testdata/interfaces.java.h.golden @@ -33,6 +33,18 @@ extern jmethodID proxy_class_interfaces_I3_cons; int32_t cproxyinterfaces_I3_F(int32_t refnum); +extern jclass proxy_class_interfaces_LargerI; +extern jmethodID proxy_class_interfaces_LargerI_cons; + +void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum); + +int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum); + +extern jclass proxy_class_interfaces_SameI; +extern jmethodID proxy_class_interfaces_SameI_cons; + +int32_t cproxyinterfaces_SameI_Rand(int32_t refnum); + extern jclass proxy_class_interfaces_WithParam; extern jmethodID proxy_class_interfaces_WithParam_cons; diff --git a/bind/testdata/interfaces.objc.go.h.golden b/bind/testdata/interfaces.objc.go.h.golden index ddef052..3915b55 100644 --- a/bind/testdata/interfaces.objc.go.h.golden +++ b/bind/testdata/interfaces.objc.go.h.golden @@ -14,6 +14,12 @@ int32_t cproxyinterfaces_I_Rand(int32_t refnum); int32_t cproxyinterfaces_I3_F(int32_t refnum); +void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum); + +int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum); + +int32_t cproxyinterfaces_SameI_Rand(int32_t refnum); + 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 9e75266..71262da 100644 --- a/bind/testdata/interfaces.objc.h.golden +++ b/bind/testdata/interfaces.objc.h.golden @@ -16,6 +16,10 @@ @protocol GoInterfacesI2; @protocol GoInterfacesI3; @class GoInterfacesI3; +@protocol GoInterfacesLargerI; +@class GoInterfacesLargerI; +@protocol GoInterfacesSameI; +@class GoInterfacesSameI; @protocol GoInterfacesWithParam; @class GoInterfacesWithParam; @@ -47,6 +51,15 @@ - (GoInterfacesI1*)f; @end +@protocol GoInterfacesLargerI +- (void)anotherFunc; +- (int32_t)rand; +@end + +@protocol GoInterfacesSameI +- (int32_t)rand; +@end + @protocol GoInterfacesWithParam - (void)hasParam:(BOOL)p0; @end @@ -63,6 +76,10 @@ FOUNDATION_EXPORT id GoInterfacesSeven(); @class GoInterfacesI3; +@class GoInterfacesLargerI; + +@class GoInterfacesSameI; + @class GoInterfacesWithParam; @interface GoInterfacesError : NSObject { @@ -89,6 +106,23 @@ FOUNDATION_EXPORT id GoInterfacesSeven(); - (GoInterfacesI1*)f; @end +@interface GoInterfacesLargerI : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +- (void)anotherFunc; +- (int32_t)rand; +@end + +@interface GoInterfacesSameI : NSObject { +} +@property(strong, readonly) id _ref; + +- (id)initWithRef:(id)ref; +- (int32_t)rand; +@end + @interface GoInterfacesWithParam : NSObject { } @property(strong, readonly) id _ref; diff --git a/bind/testdata/interfaces.objc.m.golden b/bind/testdata/interfaces.objc.m.golden index 7c6dafe..06fcd45 100644 --- a/bind/testdata/interfaces.objc.m.golden +++ b/bind/testdata/interfaces.objc.m.golden @@ -113,6 +113,49 @@ static NSString* errDomain = @"go.interfaces"; @end +@implementation GoInterfacesLargerI { +} + +- (id)initWithRef:(id)ref { + self = [super init]; + if (self) { __ref = ref; } + return self; +} + +- (void)anotherFunc { + int32_t refnum = go_seq_go_to_refnum(self._ref); + proxyinterfaces_LargerI_AnotherFunc(refnum); +} + +- (int32_t)rand { + int32_t refnum = go_seq_go_to_refnum(self._ref); + int32_t r0 = proxyinterfaces_LargerI_Rand(refnum); + int32_t _ret0_ = (int32_t)r0; + return _ret0_; +} + +@end + + +@implementation GoInterfacesSameI { +} + +- (id)initWithRef:(id)ref { + self = [super init]; + if (self) { __ref = ref; } + return self; +} + +- (int32_t)rand { + int32_t refnum = go_seq_go_to_refnum(self._ref); + int32_t r0 = proxyinterfaces_SameI_Rand(refnum); + int32_t _ret0_ = (int32_t)r0; + return _ret0_; +} + +@end + + @implementation GoInterfacesWithParam { } @@ -231,6 +274,31 @@ int32_t cproxyinterfaces_I3_F(int32_t refnum) { } } +void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum) { + @autoreleasepool { + id o = go_seq_objc_from_refnum(refnum); + [o anotherFunc]; + } +} + +int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum) { + @autoreleasepool { + id o = go_seq_objc_from_refnum(refnum); + int32_t returnVal = [o rand]; + int32_t _returnVal = (int32_t)returnVal; + return _returnVal; + } +} + +int32_t cproxyinterfaces_SameI_Rand(int32_t refnum) { + @autoreleasepool { + id o = go_seq_objc_from_refnum(refnum); + int32_t returnVal = [o rand]; + int32_t _returnVal = (int32_t)returnVal; + return _returnVal; + } +} + void cproxyinterfaces_WithParam_HasParam(int32_t refnum, char p0) { @autoreleasepool { id o = go_seq_objc_from_refnum(refnum); diff --git a/bind/testpkg/secondpkg/secondpkg.go b/bind/testpkg/secondpkg/secondpkg.go index ae87e11..94f3e31 100644 --- a/bind/testpkg/secondpkg/secondpkg.go +++ b/bind/testpkg/secondpkg/secondpkg.go @@ -7,6 +7,14 @@ package secondpkg type ( + Ser interface { + S(_ *S) + } + + IF interface { + F() + } + I interface { F(i int) int } diff --git a/bind/testpkg/testpkg.go b/bind/testpkg/testpkg.go index 366a539..c3af614 100644 --- a/bind/testpkg/testpkg.go +++ b/bind/testpkg/testpkg.go @@ -442,8 +442,13 @@ type ( ImportedI interface { F(_ secondpkg.I) } + + AnSer struct{} ) +func (_ *AnSer) S(_ *secondpkg.S) { +} + func NewImportedFields() *ImportedFields { return &ImportedFields{ I: NewImportedI(), @@ -471,6 +476,10 @@ func CallImportedI(i secondpkg.I) { i.F(0) } +func NewSer() *AnSer { + return nil +} + func NewSimpleS() *simplepkg.S { return nil } diff --git a/cmd/gobind/main.go b/cmd/gobind/main.go index a4c4f98..5e4b953 100644 --- a/cmd/gobind/main.go +++ b/cmd/gobind/main.go @@ -48,8 +48,9 @@ func main() { } var allPkg []*types.Package + imp := importer.Default() for _, arg := range flag.Args() { - pkg, err := importer.Default().Import(arg) + pkg, err := imp.Import(arg) if err != nil { fmt.Fprintf(os.Stderr, "could not import package %s: %v", arg, err) os.Exit(1) diff --git a/cmd/gomobile/bind.go b/cmd/gomobile/bind.go index 5b2b62c..bac5645 100644 --- a/cmd/gomobile/bind.go +++ b/cmd/gomobile/bind.go @@ -380,6 +380,7 @@ func loadExportData(pkgs []*build.Package, env []string, args ...string) ([]*typ return nil, err } typePkgs := make([]*types.Package, len(pkgs)) + imp := importer.Default() for i, p := range pkgs { importPath := p.ImportPath src := filepath.Join(pkgdir(env), importPath+".a") @@ -395,7 +396,7 @@ func loadExportData(pkgs []*build.Package, env []string, args ...string) ([]*typ build.Default = ctx // copy build.Default.GOARCH = goarch build.Default.GOPATH = fakegopath - p, err := importer.Default().Import(importPath) + p, err := imp.Import(importPath) build.Default = oldDefault if err != nil { return nil, err