mobile/bind: don't force Java classes to extend stub classes
Requiring user code to extend Go interface Stubs to be able to pass Java objects to Go is clumsy and use up the single extend slot. Instead, support (and enforce) java classes to implement translated Go interface directly. This is similar to how ObjC works. The stub classes are now gone, and users of gobind Java APIs need to update their code to implement interfaces directly. Change-Id: I880bb7c8e89d3c21210b2ab2c85ced8d7859ff48 Reviewed-on: https://go-review.googlesource.com/21313 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
07a529f836
commit
5e11c20fc0
@ -27,7 +27,7 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
|
||||
fields := exportedFields(T)
|
||||
methods := exportedMethodSet(types.NewPointer(obj.Type()))
|
||||
|
||||
impls := []string{"go.Seq.Object"}
|
||||
var impls []string
|
||||
pT := types.NewPointer(obj.Type())
|
||||
for _, iface := range g.allIntf {
|
||||
if types.AssignableTo(pT, iface.obj.Type()) {
|
||||
@ -38,14 +38,15 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
|
||||
impls = append(impls, n)
|
||||
}
|
||||
}
|
||||
g.Printf("public static final class %s implements %s {\n", obj.Name(), strings.Join(impls, ", "))
|
||||
g.Printf("public static final class %s extends Seq.Proxy", obj.Name())
|
||||
if len(impls) > 0 {
|
||||
g.Printf(" implements %s", strings.Join(impls, ", "))
|
||||
}
|
||||
g.Printf(" {\n")
|
||||
g.Indent()
|
||||
|
||||
g.Printf("private final go.Seq.Ref ref;\n\n")
|
||||
|
||||
n := obj.Name()
|
||||
g.Printf("private %s(go.Seq.Ref ref) { this.ref = ref; }\n\n", n)
|
||||
g.Printf("public final go.Seq.Ref ref() { return ref; }\n\n")
|
||||
g.Printf("private %s(go.Seq.Ref ref) { super(ref); }\n\n", n)
|
||||
|
||||
for _, f := range fields {
|
||||
if t := f.Type(); !g.isSupported(t) {
|
||||
@ -136,20 +137,8 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
|
||||
g.Printf("}\n\n")
|
||||
}
|
||||
|
||||
func (g *javaGen) genInterfaceStub(o *types.TypeName, m *types.Interface) {
|
||||
g.Printf("public static abstract class Stub implements %s {\n", o.Name())
|
||||
g.Indent()
|
||||
|
||||
g.Printf("private final go.Seq.Ref ref;\n")
|
||||
g.Printf("public Stub() {\n ref = go.Seq.createRef(this);\n}\n\n")
|
||||
g.Printf("public final go.Seq.Ref ref() { return ref; }\n\n")
|
||||
|
||||
g.Outdent()
|
||||
g.Printf("}\n\n")
|
||||
}
|
||||
|
||||
func (g *javaGen) genInterface(iface interfaceInfo) {
|
||||
exts := []string{"go.Seq.Object"}
|
||||
var exts []string
|
||||
numM := iface.t.NumMethods()
|
||||
for _, other := range g.allIntf {
|
||||
// Only extend interfaces with fewer methods to avoid circular references
|
||||
@ -161,10 +150,13 @@ func (g *javaGen) genInterface(iface interfaceInfo) {
|
||||
exts = append(exts, n)
|
||||
}
|
||||
}
|
||||
g.Printf("public interface %s extends %s {\n", iface.obj.Name(), strings.Join(exts, ", "))
|
||||
g.Printf("public interface %s", iface.obj.Name())
|
||||
if len(exts) > 0 {
|
||||
g.Printf(" extends %s", strings.Join(exts, ", "))
|
||||
}
|
||||
g.Printf(" {\n")
|
||||
g.Indent()
|
||||
|
||||
methodSigErr := false
|
||||
for _, m := range iface.summary.callable {
|
||||
if !g.isSigSupported(m.Type()) {
|
||||
g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
|
||||
@ -172,14 +164,8 @@ func (g *javaGen) genInterface(iface interfaceInfo) {
|
||||
}
|
||||
g.genFuncSignature(m, false, true)
|
||||
}
|
||||
if methodSigErr {
|
||||
return // skip stub generation, more of the same errors
|
||||
}
|
||||
|
||||
if iface.summary.implementable {
|
||||
g.genInterfaceStub(iface.obj, iface.t)
|
||||
}
|
||||
|
||||
g.Printf("\n")
|
||||
g.Printf(javaProxyPreamble, iface.obj.Name())
|
||||
g.Indent()
|
||||
|
||||
@ -1099,12 +1085,8 @@ func (g *javaGen) genJava() error {
|
||||
}
|
||||
|
||||
const (
|
||||
javaProxyPreamble = `static final class Proxy implements %s {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
javaProxyPreamble = `static final class Proxy extends Seq.Proxy implements %s {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
`
|
||||
javaPreamble = `// Java class %[1]s.%[2]s is a proxy for talking to a Go program.
|
||||
|
@ -5,6 +5,7 @@
|
||||
package go;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
// Seq is a sequence of machine-dependent encoded values.
|
||||
@ -15,7 +16,7 @@ public class Seq {
|
||||
// also known to bind/seq/ref.go and bind/objc/seq_darwin.m
|
||||
private static final int NULL_REFNUM = 41;
|
||||
|
||||
// use single Ref for null Seq.Object
|
||||
// use single Ref for null Object
|
||||
public static final Ref nullRef = new Ref(NULL_REFNUM, null);
|
||||
|
||||
static {
|
||||
@ -51,14 +52,11 @@ public class Seq {
|
||||
static native void setContext(java.lang.Object ctx);
|
||||
|
||||
public static void incRefnum(int refnum) {
|
||||
Ref ref = tracker.get(refnum);
|
||||
tracker.inc(ref);
|
||||
tracker.incRefnum(refnum);
|
||||
}
|
||||
|
||||
public static int incRef(Seq.Object o) {
|
||||
Ref ref = o.ref();
|
||||
tracker.inc(ref);
|
||||
return ref.refnum;
|
||||
public static int incRef(Object o) {
|
||||
return tracker.inc(o);
|
||||
}
|
||||
|
||||
public static Ref getRef(int refnum) {
|
||||
@ -71,31 +69,33 @@ public class Seq {
|
||||
// Informs the Go ref tracker that Java is done with this ref.
|
||||
static native void destroyRef(int refnum);
|
||||
|
||||
// createRef creates a Ref to a Java object.
|
||||
public static Ref createRef(Seq.Object o) {
|
||||
return tracker.createRef(o);
|
||||
}
|
||||
|
||||
// decRef is called from seq.FinalizeRef
|
||||
static void decRef(int refnum) {
|
||||
tracker.dec(refnum);
|
||||
}
|
||||
|
||||
// An Object is a Java object that matches a Go object.
|
||||
// The implementation of the object may be in either Java or Go,
|
||||
// with a proxy instance in the other language passing calls
|
||||
// through to the other language.
|
||||
//
|
||||
// Don't implement an Object directly. Instead, look for the
|
||||
// generated abstract Stub.
|
||||
public interface Object {
|
||||
public Ref ref();
|
||||
// A Proxy is a Java object that proxies a Go object.
|
||||
public static abstract class Proxy {
|
||||
private final Ref ref;
|
||||
|
||||
protected Proxy(Ref ref) {
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
public final int incRefnum() {
|
||||
// The Go reference count need to be bumped while the
|
||||
// refnum is passed to Go, to avoid finalizing and
|
||||
// invalidating it before being translated on the Go side.
|
||||
int refnum = ref.refnum;
|
||||
incGoRef(refnum);
|
||||
return refnum;
|
||||
}
|
||||
}
|
||||
|
||||
// A Ref is an object tagged with an integer for passing back and
|
||||
// forth across the language boundary.
|
||||
//
|
||||
// A Ref may represent either an instance of a Java Object subclass,
|
||||
// A Ref may represent either an instance of a Java object,
|
||||
// or an instance of a Go object. The explicit allocation of a Ref
|
||||
// is used to pin Go object instances when they are passed to Java.
|
||||
// The Go Seq library maintains a reference to the instance in a map
|
||||
@ -106,11 +106,11 @@ public class Seq {
|
||||
// refnum > 0: Java object tracked by Go
|
||||
public final int refnum;
|
||||
|
||||
int refcnt; // for Java obj: track how many times sent to Go.
|
||||
private int refcnt; // for Java obj: track how many times sent to Go.
|
||||
|
||||
public final Seq.Object obj; // for Java obj: pointers to the Java obj.
|
||||
public final Object obj; // for Java obj: pointers to the Java obj.
|
||||
|
||||
Ref(int refnum, Seq.Object o) {
|
||||
Ref(int refnum, Object o) {
|
||||
this.refnum = refnum;
|
||||
this.refcnt = 0;
|
||||
this.obj = o;
|
||||
@ -124,6 +124,14 @@ public class Seq {
|
||||
}
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
void inc() {
|
||||
// Count how many times this ref's Java object is passed to Go.
|
||||
if (refcnt == Integer.MAX_VALUE) {
|
||||
throw new RuntimeException("refnum " + refnum + " overflow");
|
||||
}
|
||||
refcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
static final RefTracker tracker = new RefTracker();
|
||||
@ -142,32 +150,44 @@ public class Seq {
|
||||
// The Ref obj field is non-null.
|
||||
// This map pins Java objects so they don't get GCed while the
|
||||
// only reference to them is held by Go code.
|
||||
private RefMap javaObjs = new RefMap();
|
||||
private final RefMap javaObjs = new RefMap();
|
||||
|
||||
// Java objects to refnum
|
||||
private final IdentityHashMap<Object, Integer> javaRefs = new IdentityHashMap<>();
|
||||
|
||||
// inc increments the reference count of a Java object when it
|
||||
// is sent to Go.
|
||||
synchronized void inc(Ref ref) {
|
||||
int refnum = ref.refnum;
|
||||
if (refnum <= 0) {
|
||||
// We don't keep track of the Go object ourselves, but
|
||||
// the Go reference count need to be bumped while the
|
||||
// refnum is passed to Go, to avoid finalizing and
|
||||
// invalidating it before being translated on the Go side.
|
||||
incGoRef(refnum);
|
||||
return;
|
||||
// is sent to Go. inc returns the refnum for the object.
|
||||
synchronized int inc(Object o) {
|
||||
if (o == null) {
|
||||
return NULL_REFNUM;
|
||||
}
|
||||
if (refnum == NULL_REFNUM) {
|
||||
return;
|
||||
if (o instanceof Proxy) {
|
||||
return ((Proxy)o).incRefnum();
|
||||
}
|
||||
// Count how many times this ref's Java object is passed to Go.
|
||||
if (ref.refcnt == Integer.MAX_VALUE) {
|
||||
throw new RuntimeException("refnum " + refnum + " overflow");
|
||||
Integer refnumObj = javaRefs.get(o);
|
||||
if (refnumObj == null) {
|
||||
if (next == Integer.MAX_VALUE) {
|
||||
throw new RuntimeException("createRef overflow for " + o);
|
||||
}
|
||||
refnumObj = next++;
|
||||
javaRefs.put(o, refnumObj);
|
||||
}
|
||||
ref.refcnt++;
|
||||
Ref obj = javaObjs.get(refnum);
|
||||
if (obj == null) {
|
||||
int refnum = refnumObj;
|
||||
Ref ref = javaObjs.get(refnum);
|
||||
if (ref == null) {
|
||||
ref = new Ref(refnum, o);
|
||||
javaObjs.put(refnum, ref);
|
||||
}
|
||||
ref.inc();
|
||||
return refnum;
|
||||
}
|
||||
|
||||
synchronized void incRefnum(int refnum) {
|
||||
Ref ref = javaObjs.get(refnum);
|
||||
if (ref == null) {
|
||||
throw new RuntimeException("referenced Java object is not found: refnum="+refnum);
|
||||
}
|
||||
ref.inc();
|
||||
}
|
||||
|
||||
// dec decrements the reference count of a Java object when
|
||||
@ -192,21 +212,10 @@ public class Seq {
|
||||
obj.refcnt--;
|
||||
if (obj.refcnt <= 0) {
|
||||
javaObjs.remove(refnum);
|
||||
javaRefs.remove(obj.obj);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized Ref createRef(Seq.Object o) {
|
||||
if (o == null) {
|
||||
return Seq.nullRef;
|
||||
}
|
||||
if (next == Integer.MAX_VALUE) {
|
||||
throw new RuntimeException("createRef overflow for " + o);
|
||||
}
|
||||
int refnum = next++;
|
||||
Ref ref = new Ref(refnum, o);
|
||||
return ref;
|
||||
}
|
||||
|
||||
// get returns an existing Ref to either a Java or Go object.
|
||||
// It may be the first time we have seen the Go object.
|
||||
//
|
||||
|
@ -17,12 +17,12 @@ import go.benchmark.Benchmark;
|
||||
|
||||
public class SeqBench extends InstrumentationTestCase {
|
||||
|
||||
public static class AnI extends Benchmark.I.Stub {
|
||||
public static class AnI implements Benchmark.I {
|
||||
@Override public void F() {
|
||||
}
|
||||
}
|
||||
|
||||
private static class Benchmarks extends Benchmark.Benchmarks.Stub {
|
||||
private static class Benchmarks implements Benchmark.Benchmarks {
|
||||
private static Map<String, Runnable> benchmarks;
|
||||
private static ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
|
@ -216,7 +216,7 @@ public class SeqTest extends InstrumentationTestCase {
|
||||
assertEquals("S should be collected", 1, collected);
|
||||
}
|
||||
|
||||
private class AnI extends Testpkg.I.Stub {
|
||||
private class AnI implements Testpkg.I {
|
||||
public void E() throws Exception {
|
||||
throw new Exception("my exception from E");
|
||||
}
|
||||
@ -355,7 +355,7 @@ public class SeqTest extends InstrumentationTestCase {
|
||||
|
||||
private int countI = 0;
|
||||
|
||||
private class CountI extends Testpkg.I.Stub {
|
||||
private class CountI implements Testpkg.I {
|
||||
public void F() { countI++; }
|
||||
|
||||
public void E() throws Exception {}
|
||||
@ -425,7 +425,7 @@ public class SeqTest extends InstrumentationTestCase {
|
||||
|
||||
//test if we have JNI local reference table overflow error
|
||||
public void testLocalReferenceOverflow() {
|
||||
Testpkg.CallWithCallback(new Testpkg.GoCallback.Stub() {
|
||||
Testpkg.CallWithCallback(new Testpkg.GoCallback() {
|
||||
|
||||
@Override
|
||||
public void VarUpdate() {
|
||||
@ -435,7 +435,7 @@ public class SeqTest extends InstrumentationTestCase {
|
||||
}
|
||||
|
||||
public void testNullReferences() {
|
||||
assertTrue(Testpkg.CallWithNull(null, new Testpkg.NullTest.Stub() {
|
||||
assertTrue(Testpkg.CallWithNull(null, new Testpkg.NullTest() {
|
||||
public Testpkg.NullTest Null() {
|
||||
return null;
|
||||
}
|
||||
@ -445,7 +445,7 @@ public class SeqTest extends InstrumentationTestCase {
|
||||
}
|
||||
|
||||
public void testPassByteArray() {
|
||||
Testpkg.PassByteArray(new Testpkg.B.Stub() {
|
||||
Testpkg.PassByteArray(new Testpkg.B() {
|
||||
@Override public void B(byte[] b) {
|
||||
byte[] want = new byte[]{1, 2, 3, 4};
|
||||
MoreAsserts.assertEquals("bytes should match", want, b);
|
||||
@ -468,14 +468,14 @@ public class SeqTest extends InstrumentationTestCase {
|
||||
}
|
||||
|
||||
public void testGoroutineCallback() {
|
||||
Testpkg.GoroutineCallback(new Testpkg.Receiver.Stub() {
|
||||
Testpkg.GoroutineCallback(new Testpkg.Receiver() {
|
||||
@Override public void Hello(String msg) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportedPkg() {
|
||||
Testpkg.CallImportedI(new Secondpkg.I.Stub() {
|
||||
Testpkg.CallImportedI(new Secondpkg.I() {
|
||||
@Override public long F(long i) {
|
||||
return i;
|
||||
}
|
||||
@ -505,13 +505,13 @@ public class SeqTest extends InstrumentationTestCase {
|
||||
public void testRoundtripEquality() {
|
||||
Testpkg.I want = new AnI();
|
||||
assertTrue("java object passed through Go should not be wrapped", want == Testpkg.IDup(want));
|
||||
Testpkg.InterfaceDupper idup = new Testpkg.InterfaceDupper.Stub(){
|
||||
Testpkg.InterfaceDupper idup = new Testpkg.InterfaceDupper(){
|
||||
@Override public Testpkg.Interface IDup(Testpkg.Interface i) {
|
||||
return i;
|
||||
}
|
||||
};
|
||||
assertTrue("Go interface passed through Java should not be wrapped", Testpkg.CallIDupper(idup));
|
||||
Testpkg.ConcreteDupper cdup = new Testpkg.ConcreteDupper.Stub(){
|
||||
Testpkg.ConcreteDupper cdup = new Testpkg.ConcreteDupper(){
|
||||
@Override public Testpkg.Concrete CDup(Testpkg.Concrete c) {
|
||||
return c;
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ Java_go_Seq_init(JNIEnv *env, jclass clazz) {
|
||||
if (seq_incRefnum == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.incRefnum");
|
||||
}
|
||||
seq_incRef = (*env)->GetStaticMethodID(env, seq_class, "incRef", "(Lgo/Seq$Object;)I");
|
||||
seq_incRef = (*env)->GetStaticMethodID(env, seq_class, "incRef", "(Ljava/lang/Object;)I");
|
||||
if (seq_incRef == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.incRef");
|
||||
}
|
||||
@ -323,7 +323,7 @@ Java_go_Seq_init(JNIEnv *env, jclass clazz) {
|
||||
if (ref_class == NULL) {
|
||||
LOG_FATAL("failed to find the Seq.Ref class");
|
||||
}
|
||||
ref_objField = (*env)->GetFieldID(env, ref_class, "obj", "Lgo/Seq$Object;");
|
||||
ref_objField = (*env)->GetFieldID(env, ref_class, "obj", "Ljava/lang/Object;");
|
||||
if (ref_objField == NULL) {
|
||||
LOG_FATAL("failed to find the Seq.Ref.obj field");
|
||||
}
|
||||
|
27
bind/testdata/ignore.java.golden
vendored
27
bind/testdata/ignore.java.golden
vendored
@ -19,12 +19,8 @@ public abstract class Ignore {
|
||||
|
||||
private static native void init();
|
||||
|
||||
public static final class S implements go.Seq.Object, I {
|
||||
private final go.Seq.Ref ref;
|
||||
|
||||
private S(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
public static final class S extends Seq.Proxy implements I {
|
||||
private S(go.Seq.Ref ref) { super(ref); }
|
||||
|
||||
// skipped field S.F with unsupported type: *types.Interface
|
||||
|
||||
@ -53,27 +49,14 @@ public abstract class Ignore {
|
||||
}
|
||||
}
|
||||
|
||||
public interface I extends go.Seq.Object {
|
||||
public interface I {
|
||||
// skipped method I.Argument with unsupported parameter or return types
|
||||
|
||||
// skipped method I.Result with unsupported parameter or return types
|
||||
|
||||
public static abstract class Stub implements I {
|
||||
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 I {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements I {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
// skipped method I.Argument with unsupported parameter or return types
|
||||
|
||||
|
132
bind/testdata/interfaces.java.golden
vendored
132
bind/testdata/interfaces.java.golden
vendored
@ -19,167 +19,83 @@ public abstract class Interfaces {
|
||||
|
||||
private static native void init();
|
||||
|
||||
public interface Error extends go.Seq.Object {
|
||||
public interface Error {
|
||||
public void Err() throws Exception;
|
||||
public static abstract class Stub implements Error {
|
||||
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 Error {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements Error {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native void Err() throws Exception;
|
||||
}
|
||||
}
|
||||
|
||||
public interface I extends go.Seq.Object {
|
||||
public interface I {
|
||||
public int Rand();
|
||||
public static abstract class Stub implements I {
|
||||
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 I {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements I {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native int Rand();
|
||||
}
|
||||
}
|
||||
|
||||
public interface I1 extends go.Seq.Object {
|
||||
public interface I1 {
|
||||
public void J();
|
||||
static final class Proxy implements I1 {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements I1 {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native void J();
|
||||
}
|
||||
}
|
||||
|
||||
public interface I2 extends go.Seq.Object {
|
||||
public interface I2 {
|
||||
public void G();
|
||||
static final class Proxy implements I2 {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements I2 {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native void G();
|
||||
}
|
||||
}
|
||||
|
||||
public interface I3 extends go.Seq.Object {
|
||||
public interface I3 {
|
||||
public I1 F();
|
||||
public static abstract class Stub implements I3 {
|
||||
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 I3 {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements I3 {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native I1 F();
|
||||
}
|
||||
}
|
||||
|
||||
public interface LargerI extends go.Seq.Object, I, SameI {
|
||||
public interface LargerI extends 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; }
|
||||
static final class Proxy extends Seq.Proxy implements LargerI {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native void AnotherFunc();
|
||||
public native int Rand();
|
||||
}
|
||||
}
|
||||
|
||||
public interface SameI extends go.Seq.Object {
|
||||
public interface SameI {
|
||||
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; }
|
||||
static final class Proxy extends Seq.Proxy implements SameI {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native int Rand();
|
||||
}
|
||||
}
|
||||
|
||||
public interface WithParam extends go.Seq.Object {
|
||||
public interface WithParam {
|
||||
public void HasParam(boolean p0);
|
||||
public static abstract class Stub implements WithParam {
|
||||
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 WithParam {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements WithParam {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native void HasParam(boolean p0);
|
||||
}
|
||||
|
27
bind/testdata/issue10788.java.golden
vendored
27
bind/testdata/issue10788.java.golden
vendored
@ -19,12 +19,8 @@ public abstract class Issue10788 {
|
||||
|
||||
private static native void init();
|
||||
|
||||
public static final class TestStruct implements go.Seq.Object {
|
||||
private final go.Seq.Ref ref;
|
||||
|
||||
private TestStruct(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
public static final class TestStruct extends Seq.Proxy {
|
||||
private TestStruct(go.Seq.Ref ref) { super(ref); }
|
||||
|
||||
public final native String getValue();
|
||||
public final native void setValue(String v);
|
||||
@ -58,25 +54,12 @@ public abstract class Issue10788 {
|
||||
}
|
||||
}
|
||||
|
||||
public interface TestInterface extends go.Seq.Object {
|
||||
public interface TestInterface {
|
||||
public void DoSomeWork(TestStruct s);
|
||||
public void MultipleUnnamedParams(long p0, String p1, long p2);
|
||||
public static abstract class Stub implements TestInterface {
|
||||
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 TestInterface {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements TestInterface {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native void DoSomeWork(TestStruct s);
|
||||
public native void MultipleUnnamedParams(long p0, String p1, long p2);
|
||||
|
8
bind/testdata/issue12328.java.golden
vendored
8
bind/testdata/issue12328.java.golden
vendored
@ -19,12 +19,8 @@ public abstract class Issue12328 {
|
||||
|
||||
private static native void init();
|
||||
|
||||
public static final class T implements go.Seq.Object {
|
||||
private final go.Seq.Ref ref;
|
||||
|
||||
private T(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
public static final class T extends Seq.Proxy {
|
||||
private T(go.Seq.Ref ref) { super(ref); }
|
||||
|
||||
public final native String getErr();
|
||||
public final native void setErr(String v);
|
||||
|
19
bind/testdata/issue12403.java.golden
vendored
19
bind/testdata/issue12403.java.golden
vendored
@ -19,25 +19,12 @@ public abstract class Issue12403 {
|
||||
|
||||
private static native void init();
|
||||
|
||||
public interface Parsable extends go.Seq.Object {
|
||||
public interface Parsable {
|
||||
public String FromJSON(String jstr);
|
||||
public String ToJSON() throws Exception;
|
||||
public static abstract class Stub implements Parsable {
|
||||
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 Parsable {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements Parsable {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native String FromJSON(String jstr);
|
||||
public native String ToJSON() throws Exception;
|
||||
|
35
bind/testdata/structs.java.golden
vendored
35
bind/testdata/structs.java.golden
vendored
@ -19,12 +19,8 @@ public abstract class Structs {
|
||||
|
||||
private static native void init();
|
||||
|
||||
public static final class S implements go.Seq.Object {
|
||||
private final go.Seq.Ref ref;
|
||||
|
||||
private S(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
public static final class S extends Seq.Proxy {
|
||||
private S(go.Seq.Ref ref) { super(ref); }
|
||||
|
||||
public final native double getX();
|
||||
public final native void setX(double v);
|
||||
@ -65,12 +61,8 @@ public abstract class Structs {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class S2 implements go.Seq.Object, I {
|
||||
private final go.Seq.Ref ref;
|
||||
|
||||
private S2(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
public static final class S2 extends Seq.Proxy implements I {
|
||||
private S2(go.Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native void M();
|
||||
public native String String();
|
||||
@ -91,24 +83,11 @@ public abstract class Structs {
|
||||
}
|
||||
}
|
||||
|
||||
public interface I extends go.Seq.Object {
|
||||
public interface I {
|
||||
public void M();
|
||||
public static abstract class Stub implements I {
|
||||
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 I {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements I {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
public native void M();
|
||||
}
|
||||
|
27
bind/testdata/vars.java.golden
vendored
27
bind/testdata/vars.java.golden
vendored
@ -19,12 +19,8 @@ public abstract class Vars {
|
||||
|
||||
private static native void init();
|
||||
|
||||
public static final class S implements go.Seq.Object, I {
|
||||
private final go.Seq.Ref ref;
|
||||
|
||||
private S(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
public static final class S extends Seq.Proxy implements I {
|
||||
private S(go.Seq.Ref ref) { super(ref); }
|
||||
|
||||
@Override public boolean equals(Object o) {
|
||||
if (o == null || !(o instanceof S)) {
|
||||
@ -45,23 +41,10 @@ public abstract class Vars {
|
||||
}
|
||||
}
|
||||
|
||||
public interface I extends go.Seq.Object {
|
||||
public static abstract class Stub implements I {
|
||||
private final go.Seq.Ref ref;
|
||||
public Stub() {
|
||||
ref = go.Seq.createRef(this);
|
||||
}
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
|
||||
}
|
||||
public interface I {
|
||||
|
||||
static final class Proxy implements I {
|
||||
private go.Seq.Ref ref;
|
||||
|
||||
Proxy(go.Seq.Ref ref) { this.ref = ref; }
|
||||
|
||||
public final go.Seq.Ref ref() { return ref; }
|
||||
static final class Proxy extends Seq.Proxy implements I {
|
||||
Proxy(Seq.Ref ref) { super(ref); }
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -90,27 +90,23 @@ For a Go interface:
|
||||
p.Print("Hello, World!")
|
||||
}
|
||||
|
||||
gobind generates a Java stub that can be used to implement a Printer:
|
||||
gobind generates a Java interface that can be used to implement a Printer:
|
||||
|
||||
public abstract class Myfmt {
|
||||
private Myfmt() {}
|
||||
public interface Printer {
|
||||
public void Print(String s);
|
||||
|
||||
public static abstract class Stub implements Printer {
|
||||
...
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
public static void PrintHello(Printer p) { ... }
|
||||
}
|
||||
|
||||
You can extend Myfmt.Printer.Stub to implement the Printer interface, and
|
||||
pass it to Go using the PrintHello package function:
|
||||
You can implement Myfmt.Printer, and pass it to Go using the PrintHello
|
||||
package function:
|
||||
|
||||
public class SysPrint extends Myfmt.Printer.Stub {
|
||||
public class SysPrint implements Myfmt.Printer {
|
||||
public void Print(String s) {
|
||||
System.out.println(s);
|
||||
}
|
||||
@ -205,8 +201,8 @@ of G, then the language bindings on each side must keep G and J live
|
||||
even if they are otherwise unreachable.
|
||||
|
||||
We recommend that implementations of foreign interfaces do not hold
|
||||
references to proxies of objects. That is: if you extend a Stub in
|
||||
Java, do not store an instance of Seq.Object inside it.
|
||||
references to proxies of objects. That is: if you implement a Go
|
||||
interface in Java, do not store an instance of Seq.Object inside it.
|
||||
|
||||
Further reading
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user