diff --git a/bind/gengo.go b/bind/gengo.go index 0beccf6..49f1daf 100644 --- a/bind/gengo.go +++ b/bind/gengo.go @@ -352,7 +352,7 @@ func (g *goGen) genRead(valName, seqName string, typ types.Type) { g.Printf("if %s_ref.Num < 0 { // go object \n", valName) g.Printf(" %s = %s_ref.Get().(%s.%s)\n", valName, valName, g.pkg.Name(), o.Name()) if hasProxy { - g.Printf("} else { // foreign object \n") + g.Printf("} else if %s_ref.Num != seq.NullRefNum { // foreign object \n", valName) g.Printf(" %s = (*proxy%s)(%s_ref)\n", valName, o.Name(), valName) } g.Printf("}\n") diff --git a/bind/java/Seq.java b/bind/java/Seq.java index 2e8879a..1c801d0 100644 --- a/bind/java/Seq.java +++ b/bind/java/Seq.java @@ -77,6 +77,8 @@ public class Seq { public native void writeByteArray(byte[] v); public void writeRef(Ref ref) { + if (ref == null) + ref = RefTracker.nullRef; tracker.inc(ref); writeInt32(ref.refnum); } @@ -172,9 +174,10 @@ public class Seq { static final class RefTracker { private static final int REF_OFFSET = 42; + private static final int NULL_REFNUM = 41; // also known to bind/seq/ref.go // use single Ref for null Seq.Object - private static final Ref nullRef = new Ref(REF_OFFSET - 1, null); + private static final Ref nullRef = new Ref(NULL_REFNUM, null); // Next Java object reference number. // diff --git a/bind/java/SeqTest.java b/bind/java/SeqTest.java index 8dba673..e1020da 100644 --- a/bind/java/SeqTest.java +++ b/bind/java/SeqTest.java @@ -381,4 +381,12 @@ public class SeqTest extends AndroidTestCase { String got = n.getErr(); assertEquals("want back the error message we set", want, got); } + + public void testNullReferences() { + assertTrue(Testpkg.CallWithNull(null, new Testpkg.NullTest.Stub() { + public Testpkg.NullTest Null() { + return null; + } + })); + } } diff --git a/bind/java/testpkg/testpkg.go b/bind/java/testpkg/testpkg.go index 806e3c7..7a051d1 100644 --- a/bind/java/testpkg/testpkg.go +++ b/bind/java/testpkg/testpkg.go @@ -204,3 +204,11 @@ func ReadAsset() string { } return string(b) } + +type NullTest interface { + Null() NullTest +} + +func CallWithNull(_null NullTest, nuller NullTest) bool { + return _null == nil && nuller.Null() == nil +} diff --git a/bind/seq.go b/bind/seq.go index 05e4d24..5ba0274 100644 --- a/bind/seq.go +++ b/bind/seq.go @@ -81,7 +81,7 @@ func seqWrite(o types.Type, name string) string { t := seqType(o) if t == "Ref" { // TODO(crawshaw): do something cleaner, i.e. genWrite. - return t + "(" + name + ".ref())" + return t + "(" + name + " != null ? " + name + ".ref() : null)" } return t + "(" + name + ")" } diff --git a/bind/seq/ref.go b/bind/seq/ref.go index 2eed868..c4811f7 100644 --- a/bind/seq/ref.go +++ b/bind/seq/ref.go @@ -19,6 +19,8 @@ type countedObj struct { cnt int32 } +const NullRefNum = 41 // also known to bind/java/Seq.java + // refs stores Go objects that have been passed to another language. var refs struct { sync.Mutex diff --git a/bind/testdata/interfaces.go.golden b/bind/testdata/interfaces.go.golden index a3fa216..cebdd4e 100644 --- a/bind/testdata/interfaces.go.golden +++ b/bind/testdata/interfaces.go.golden @@ -14,7 +14,7 @@ func proxy_Add3(out, in *seq.Buffer) { param_r_ref := in.ReadRef() if param_r_ref.Num < 0 { // go object param_r = param_r_ref.Get().(interfaces.I) - } else { // foreign object + } else if param_r_ref.Num != seq.NullRefNum { // foreign object param_r = (*proxyI)(param_r_ref) } res := interfaces.Add3(param_r) @@ -26,7 +26,7 @@ func proxy_CallErr(out, in *seq.Buffer) { param_e_ref := in.ReadRef() if param_e_ref.Num < 0 { // go object param_e = param_e_ref.Get().(interfaces.Error) - } else { // foreign object + } else if param_e_ref.Num != seq.NullRefNum { // foreign object param_e = (*proxyError)(param_e_ref) } err := interfaces.CallErr(param_e) diff --git a/bind/testdata/interfaces.java.golden b/bind/testdata/interfaces.java.golden index da2e9a2..82d2d51 100644 --- a/bind/testdata/interfaces.java.golden +++ b/bind/testdata/interfaces.java.golden @@ -15,7 +15,7 @@ public abstract class Interfaces { _out = new go.Seq(); int _result; _in = new go.Seq(); - _in.writeRef(r.ref()); + _in.writeRef(r != null ? r.ref() : null); Seq.send(DESCRIPTOR, CALL_Add3, _in, _out); _result = _out.readInt32(); return _result; @@ -26,7 +26,7 @@ public abstract class Interfaces { go.Seq _out = null; _out = new go.Seq(); _in = new go.Seq(); - _in.writeRef(e.ref()); + _in.writeRef(e != null ? e.ref() : null); Seq.send(DESCRIPTOR, CALL_CallErr, _in, _out); String _err = _out.readString(); if (_err != null && !_err.isEmpty()) { @@ -222,7 +222,7 @@ public abstract class Interfaces { switch (code) { case Proxy.CALL_F: { I1 result = this.F(); - out.writeRef(result.ref()); + out.writeRef(result != null ? result.ref() : null); return; } default: diff --git a/bind/testdata/issue10788.java.golden b/bind/testdata/issue10788.java.golden index 2cf30b0..24be140 100644 --- a/bind/testdata/issue10788.java.golden +++ b/bind/testdata/issue10788.java.golden @@ -66,7 +66,7 @@ public abstract class Issue10788 { go.Seq _out = null; _in = new go.Seq(); _in.writeRef(ref); - _in.writeRef(s.ref()); + _in.writeRef(s != null ? s.ref() : null); Seq.send(DESCRIPTOR, CALL_DoSomeWork, _in, _out); } diff --git a/bind/testdata/structs.java.golden b/bind/testdata/structs.java.golden index 7b68f2d..46353cd 100644 --- a/bind/testdata/structs.java.golden +++ b/bind/testdata/structs.java.golden @@ -65,7 +65,7 @@ public abstract class Structs { _out = new go.Seq(); S _result; _in = new go.Seq(); - _in.writeRef(s.ref()); + _in.writeRef(s != null ? s.ref() : null); Seq.send(DESCRIPTOR, CALL_Identity, _in, _out); _result = new S(_out.readRef()); return _result; @@ -77,7 +77,7 @@ public abstract class Structs { _out = new go.Seq(); S _result; _in = new go.Seq(); - _in.writeRef(s.ref()); + _in.writeRef(s != null ? s.ref() : null); Seq.send(DESCRIPTOR, CALL_IdentityWithError, _in, _out); _result = new S(_out.readRef()); String _err = _out.readString(); diff --git a/bind/testdata/vars.go.golden b/bind/testdata/vars.go.golden index 5a9d02d..2665860 100644 --- a/bind/testdata/vars.go.golden +++ b/bind/testdata/vars.go.golden @@ -93,7 +93,7 @@ func var_setAnInterface(out, in *seq.Buffer) { v_ref := in.ReadRef() if v_ref.Num < 0 { // go object v = v_ref.Get().(vars.I) - } else { // foreign object + } else if v_ref.Num != seq.NullRefNum { // foreign object v = (*proxyI)(v_ref) } vars.AnInterface = v diff --git a/bind/testdata/vars.java.golden b/bind/testdata/vars.java.golden index cdc0ca4..efda725 100644 --- a/bind/testdata/vars.java.golden +++ b/bind/testdata/vars.java.golden @@ -76,7 +76,7 @@ public abstract class Vars { public static void setAStructPtr(S v) { Seq in = new Seq(); - in.writeRef(v.ref()); + in.writeRef(v != null ? v.ref() : null); Seq.send("vars.AStructPtr", 1, in, null); } @@ -154,7 +154,7 @@ public abstract class Vars { public static void setAnInterface(I v) { Seq in = new Seq(); - in.writeRef(v.ref()); + in.writeRef(v != null ? v.ref() : null); Seq.send("vars.AnInterface", 1, in, null); }