Skip to content

Commit 099c5a8

Browse files
committed
[generator] Avoid non-blittable types in native callback methods
1 parent 9b1d878 commit 099c5a8

File tree

4 files changed

+88
-1
lines changed

4 files changed

+88
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using System;
2+
using MonoDroid.Generation;
3+
using NUnit.Framework;
4+
using Xamarin.Android.Binder;
5+
6+
namespace generatortests;
7+
8+
[TestFixture]
9+
class BlittableTypeTests : CodeGeneratorTestBase
10+
{
11+
protected override CodeGenerationTarget Target => CodeGenerationTarget.XAJavaInterop1;
12+
13+
[Test]
14+
public void MethodWithBoolReturnType ()
15+
{
16+
var klass = new TestClass ("Object", "java.code.MyClass");
17+
var method = SupportTypeBuilder.CreateMethod (klass, "IsEmpty", options, "boolean");
18+
19+
klass.Methods.Add (method);
20+
21+
var actual = GetGeneratedTypeOutput (klass);
22+
23+
// Return type should be byte
24+
Assert.That (actual, Contains.Substring ("static byte n_IsEmpty"));
25+
26+
// Return statement should convert to 0 or 1
27+
Assert.That (actual, Contains.Substring ("return __this.IsEmpty () ? 1 : 0"));
28+
29+
// Ensure the marshal delegate is byte
30+
Assert.That (actual, Contains.Substring ("new _JniMarshal_PP_B"));
31+
Assert.That (actual, Does.Not.Contains ("new _JniMarshal_PP_Z"));
32+
}
33+
34+
[Test]
35+
public void MethodWithBoolParameter ()
36+
{
37+
var klass = new TestClass ("Object", "java.code.MyClass");
38+
var method = SupportTypeBuilder.CreateMethod (klass, "SetEmpty", options, "void", parameters: new Parameter ("value", "boolean", "bool", false));
39+
40+
klass.Methods.Add (method);
41+
42+
var actual = GetGeneratedTypeOutput (klass);
43+
44+
// Method parameter should be byte
45+
Assert.That (actual, Contains.Substring ("static void n_SetEmpty_Z (IntPtr jnienv, IntPtr native__this, byte native_value)"));
46+
47+
// Method should convert from 0 or 1
48+
Assert.That (actual, Contains.Substring ("var value = native_value != 0;"));
49+
50+
// Ensure the marshal delegate is byte
51+
Assert.That (actual, Contains.Substring ("new _JniMarshal_PPB_V"));
52+
Assert.That (actual, Does.Not.Contains ("new _JniMarshal_PPZ_V"));
53+
}
54+
55+
[Test]
56+
public void BoolProperty ()
57+
{
58+
var klass = SupportTypeBuilder.CreateClassWithProperty ("MyClass", "com.example.myClass", "IsEmpty", "boolean", options);
59+
var actual = GetGeneratedTypeOutput (klass);
60+
61+
// Getter return type should be byte
62+
Assert.That (actual, Contains.Substring ("static byte n_get_IsEmpty"));
63+
64+
// Getter return statement should convert to 0 or 1
65+
Assert.That (actual, Contains.Substring ("return __this.IsEmpty ? 1 : 0"));
66+
67+
// Setter parameter should be byte
68+
Assert.That (actual, Contains.Substring ("static void n_set_IsEmpty_Z (IntPtr jnienv, IntPtr native__this, byte native_value)"));
69+
70+
// Setter should convert from 0 or 1
71+
Assert.That (actual, Contains.Substring ("var value = native_value != 0;"));
72+
73+
// Ensure the marshal delegate is byte
74+
Assert.That (actual, Contains.Substring ("new _JniMarshal_PP_B"));
75+
Assert.That (actual, Does.Not.Contains ("new _JniMarshal_PP_Z"));
76+
}
77+
}

tests/generator-Tests/Unit-Tests/CodeGeneratorTestBase.cs

+9
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,14 @@ protected static string GetAssertionMessage (string header, string expected, str
131131
$"Expected:\n```\n{expected}\n```\n" +
132132
$"Actual:\n```\n{actual}\n```";
133133
}
134+
135+
protected string GetGeneratedTypeOutput (GenBase gen)
136+
{
137+
generator.Context.ContextTypes.Push (gen);
138+
generator.WriteType (gen, string.Empty, new GenerationInfo ("", "", "MyAssembly"));
139+
generator.Context.ContextTypes.Pop ();
140+
141+
return writer.ToString ();
142+
}
134143
}
135144
}

tools/generator/CodeGenerationOptions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ string GetJniTypeCode (ISymbol symbol)
217217
case "uint": return "i";
218218
case "ulong": return "j";
219219
case "ushort": return "s";
220+
case "boolean": return "B"; // We marshal boolean (Z) as byte (B)
220221
}
221222

222223
var jni_name = symbol.JniName;

tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/SymbolTable.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public SymbolTable (CodeGenerationTarget target)
5757
this.target = target;
5858

5959
AddType (new SimpleSymbol ("IntPtr.Zero", "void", "void", "V"));
60-
AddType (new SimpleSymbol ("false", "boolean", "bool", "Z"));
60+
AddType (new SimpleSymbol ("false", "boolean", "bool", "Z", "byte", from_fmt: "{0} != 0", to_fmt: "{0} ? 1 : 0"));
6161
AddType (new SimpleSymbol ("0", "byte", "sbyte", "B"));
6262
AddType (new SimpleSymbol ("(char)0", "char", "char", "C"));
6363
AddType (new SimpleSymbol ("0.0", "double", "double", "D"));

0 commit comments

Comments
 (0)