2
0
mirror of synced 2025-02-23 06:48:15 +00:00

mobile/bind: handle null references from Java in Go

The Seq Java class has a special case for null references. Expand
the special case to Go so that null references from Java are properly
translated to nil.

Fixes golang/go#14228

Change-Id: I915d1f843c9db299d6910480f6d10dae0121a3b4
Reviewed-on: https://go-review.googlesource.com/19460
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Elias Naur 2016-02-11 14:09:24 +01:00 committed by David Crawshaw
parent 46f9e01d1e
commit d1c2f486a3
12 changed files with 35 additions and 14 deletions

View File

@ -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")

View File

@ -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.
//

View File

@ -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;
}
}));
}
}

View File

@ -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
}

View File

@ -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 + ")"
}

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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);
}

View File

@ -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();

View File

@ -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

View File

@ -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);
}