Skip to content

Commit 719e615

Browse files
authored
[Hello-Java.Base] Add support for Java Callable Wrappers (#1315)
Context: 2a1e180 Update `samples/Hello-Java.Base` to use `Java.Interop.Sdk` (2a1e180), so that it (kinda, sorta) "automagically" gets support for generating Java Callable Wrappers as part of its build. Add a custom `Java.Lang.Object` subclass and use it. Update `JreTypeManager` and `JreRuntimeOptions` so that type mappings can be more easily provided without requiring a `JreTypeManager` subclass, as Java.Interop.Sdk" is not fleshed out enough to provide that information itself. (This also simplifies `TestJVM`.)
1 parent 1e7f269 commit 719e615

File tree

6 files changed

+79
-44
lines changed

6 files changed

+79
-44
lines changed

build-tools/Java.Interop.Sdk/Sdk/Sdk.targets

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464

6565
<Target Name="_BuildJavaCompileForManagedBinding"
6666
DependsOnTargets="_CollectJavaCompileForManagedBindingInputs;_JavaCollectJavacRefs"
67+
Condition=" '$(_JavaCompileForBindingInputs->Count())' != '0' "
6768
Inputs="@(_JavaCompileForBindingInputs)"
6869
Outputs="$(_JavaManagedBindingInput)">
6970
<PropertyGroup>
@@ -105,6 +106,7 @@
105106

106107
<Target Name="_GenerateApiDescription"
107108
DependsOnTargets="_CollectClassParseInputs"
109+
Condition=" '$(_ClassParseInputs->Count())' != '0' "
108110
Inputs="@(_ClassParseInputs)"
109111
Outputs="$(_JavaManagedBindingDir)api.xml">
110112
<MakeDir Directories="$(_JavaManagedBindingDir)" />
@@ -120,6 +122,7 @@
120122

121123
<Target Name="_GenerateManagedBinding"
122124
DependsOnTargets="_GenerateApiDescription"
125+
Condition=" Exists('$(_JavaManagedBindingDir)api.xml') "
123126
Inputs="$(_JavaManagedBindingDir)api.xml"
124127
Outputs="$(_JavaManagedBindingDir)$(AssemblyName).projitems">
125128
<MakeDir Directories="$(_JavaManagedBindingDir)" />

samples/Hello-Java.Base/Hello-Java.Base.csproj

+10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77
<Nullable>enable</Nullable>
88
<StartupObject>Hello.App</StartupObject>
99
</PropertyGroup>
10+
11+
<Import Project="..\..\build-tools\Java.Interop.Sdk\Sdk\Sdk.props" />
12+
<!-- Currently needs to be included so that Sdk.targets can find things -->
13+
<Import Project="..\..\TargetFrameworkDependentValues.props" />
14+
15+
<PropertyGroup>
16+
<OutputPath>$(MSBuildThisFileDirectory)bin\$(Configuration)\</OutputPath>
17+
</PropertyGroup>
1018

1119
<ItemGroup>
1220
<ProjectReference Include="..\..\src\Java.Interop\Java.Interop.csproj" />
@@ -15,4 +23,6 @@
1523
<ProjectReference Include="..\..\tests\TestJVM\TestJVM.csproj" />
1624
</ItemGroup>
1725

26+
<Import Project="..\..\build-tools\Java.Interop.Sdk\Sdk\Sdk.targets" />
27+
1828
</Project>

samples/Hello-Java.Base/Program.cs

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
4+
using System.Linq;
5+
using System.IO;
36
using System.Threading;
47

58
using Mono.Options;
@@ -26,7 +29,7 @@ public static void Main (string[] args)
2629
$"{{PATH}} to JVM to use. Default is:\n {jvmPath}",
2730
v => jvmPath = v },
2831
{ "m",
29-
"Create multiple Java VMs. This will likely creash.",
32+
"Create multiple Java VMs. This will likely crash.",
3033
v => createMultipleVMs = v != null },
3134
{ "t",
3235
$"Timing; invoke Object.hashCode() {N} times, print average.",
@@ -43,6 +46,12 @@ public static void Main (string[] args)
4346
var builder = new JreRuntimeOptions () {
4447
JniAddNativeMethodRegistrationAttributePresent = true,
4548
JvmLibraryPath = jvmPath,
49+
ClassPath = {
50+
Path.Combine (Path.GetDirectoryName (typeof (App).Assembly.Location)!, "Hello-Java.Base.jar"),
51+
},
52+
TypeMappings = {
53+
[MyJLO.JniTypeName] = typeof (MyJLO),
54+
},
4655
};
4756
builder.AddOption ("-Xcheck:jni");
4857

@@ -63,7 +72,7 @@ public static void Main (string[] args)
6372

6473
static void CreateJLO ()
6574
{
66-
var jlo = new Java.Lang.Object ();
75+
var jlo = new MyJLO ();
6776
Console.WriteLine ($"binding? {jlo.ToString ()}");
6877
}
6978

@@ -115,4 +124,9 @@ static unsafe void CreateAnotherJVM ()
115124
}
116125
}
117126
}
127+
128+
[JniTypeSignature (JniTypeName)]
129+
class MyJLO : Java.Lang.Object {
130+
internal const string JniTypeName = "net/dot/jni/sample/MyJLO";
131+
}
118132
}

src/Java.Runtime.Environment/Java.Interop/JreRuntime.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public class JreRuntimeOptions : JniRuntime.CreationOptions {
3535
public TextWriter? JniGlobalReferenceLogWriter {get; set;}
3636
public TextWriter? JniLocalReferenceLogWriter {get; set;}
3737

38+
internal Dictionary<string, Type>? typeMappings;
39+
public IDictionary<string, Type> TypeMappings => typeMappings ??= new ();
40+
3841
internal JvmLibraryHandler? LibraryHandler {get; set;}
3942

4043
public JreRuntimeOptions ()
@@ -85,7 +88,7 @@ static unsafe JreRuntimeOptions CreateJreVM (JreRuntimeOptions builder)
8588
builder.LibraryHandler = JvmLibraryHandler.Create ();
8689

8790
#if NET
88-
builder.TypeManager ??= new JreTypeManager ();
91+
builder.TypeManager ??= new JreTypeManager (builder.typeMappings);
8992
#endif // NET
9093

9194
bool onMono = Type.GetType ("Mono.Runtime", throwOnError: false) != null;

src/Java.Runtime.Environment/Java.Interop/JreTypeManager.cs

+38
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,44 @@ namespace Java.Interop {
1818

1919
public class JreTypeManager : JniRuntime.JniTypeManager {
2020

21+
IDictionary<string, Type>? typeMappings;
22+
23+
public JreTypeManager ()
24+
: this (null)
25+
{
26+
}
27+
28+
public JreTypeManager (IDictionary<string, Type>? typeMappings)
29+
{
30+
this.typeMappings = typeMappings;
31+
}
32+
33+
protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpleReference)
34+
{
35+
foreach (var t in base.GetTypesForSimpleReference (jniSimpleReference))
36+
yield return t;
37+
if (typeMappings == null)
38+
yield break;
39+
if (typeMappings.TryGetValue (jniSimpleReference, out var target))
40+
yield return target;
41+
}
42+
43+
protected override IEnumerable<string> GetSimpleReferences (Type type)
44+
{
45+
return base.GetSimpleReferences (type)
46+
.Concat (CreateSimpleReferencesEnumerator (type));
47+
}
48+
49+
IEnumerable<string> CreateSimpleReferencesEnumerator (Type type)
50+
{
51+
if (typeMappings == null)
52+
yield break;
53+
foreach (var e in typeMappings) {
54+
if (e.Value == type)
55+
yield return e.Key;
56+
}
57+
}
58+
2159
const string NotUsedInAndroid = "This code path is not used in Android projects.";
2260

2361
public override void RegisterNativeMembers (

tests/TestJVM/TestJVM.cs

+8-41
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public TestJVMOptions (Assembly? callingAssembly = null)
2323

2424
public ICollection<string> JarFilePaths {get;} = new List<string> ();
2525
public Assembly CallingAssembly {get; set;}
26-
public Dictionary<string, Type>? TypeMappings {get; set;}
2726

2827
internal JdkInfo? JdkInfo {get; set;}
2928
}
@@ -141,9 +140,13 @@ public TestJVM (string[]? jars = null, Dictionary<string, Type>? typeMappings =
141140
static TestJVMOptions CreateOptions (string[]? jarFiles, Assembly callingAssembly, Dictionary<string, Type>? typeMappings)
142141
{
143142
var o = new TestJVMOptions {
144-
TypeMappings = typeMappings,
145143
CallingAssembly = callingAssembly,
146144
};
145+
if (typeMappings != null) {
146+
foreach (var e in typeMappings) {
147+
o.TypeMappings.Add (e.Key, e.Value);
148+
}
149+
}
147150
if (jarFiles != null) {
148151
foreach (var jar in jarFiles) {
149152
o.JarFilePaths.Add (jar);
@@ -153,48 +156,12 @@ static TestJVMOptions CreateOptions (string[]? jarFiles, Assembly callingAssembl
153156
}
154157
}
155158

156-
public class TestJvmTypeManager :
157-
#if NET
158-
JreTypeManager
159-
#else // !NET
160-
JniRuntime.JniTypeManager
161-
#endif // !NET
159+
public class TestJvmTypeManager : JreTypeManager
162160
{
163161

164-
Dictionary<string, Type>? typeMappings;
165-
166-
public TestJvmTypeManager (Dictionary<string, Type>? typeMappings)
162+
public TestJvmTypeManager (IDictionary<string, Type>? typeMappings)
163+
: base (typeMappings)
167164
{
168-
this.typeMappings = typeMappings;
169-
}
170-
171-
protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpleReference)
172-
{
173-
foreach (var t in base.GetTypesForSimpleReference (jniSimpleReference))
174-
yield return t;
175-
if (typeMappings == null)
176-
yield break;
177-
Type target;
178-
#pragma warning disable CS8600 // huh?
179-
if (typeMappings.TryGetValue (jniSimpleReference, out target))
180-
yield return target;
181-
#pragma warning restore CS8600
182-
}
183-
184-
protected override IEnumerable<string> GetSimpleReferences (Type type)
185-
{
186-
return base.GetSimpleReferences (type)
187-
.Concat (CreateSimpleReferencesEnumerator (type));
188-
}
189-
190-
IEnumerable<string> CreateSimpleReferencesEnumerator (Type type)
191-
{
192-
if (typeMappings == null)
193-
yield break;
194-
foreach (var e in typeMappings) {
195-
if (e.Value == type)
196-
yield return e.Key;
197-
}
198165
}
199166
}
200167
}

0 commit comments

Comments
 (0)