Skip to content

Commit 25850ba

Browse files
authored
[jnimarshalmethod-gen] JavaInterop1 marshal methods (#1164)
Fixes: #1159 Context: c93fea0 `jnimarshalmethod-gen` is intended to generate marshal methods for any type that that: * Has `[JavaCallable]` (tested in `Java.Interop.Export-Tests.dll` and c93fea0), or * Overrides a `virtual` method which has `[JniMethodSignature]`, or * Implements an interface method which has `[JniMethodSignature]`. Thus, the intention was that it should generate marshal methods for `Java.Base-Tests`: % dotnet bin/Debug-net7.0/jnimarshalmethod-gen.dll -v bin/TestDebug-net7.0/Java.Base-Tests.dll Unable to read assembly 'bin/TestDebug-net7.0/Java.Base-Tests.dll' with symbols. Retrying to load it without them. Preparing marshal method assembly 'Java.Base-Tests-JniMarshalMethods' Processing Java.BaseTests.JavaInvoker type Processing Java.BaseTests.MyRunnable type Processing Java.BaseTests.MyIntConsumer type Marshal method assembly 'Java.Base-Tests-JniMarshalMethods' created Notably missing? No messages stating: Adding marshal method for … Also missing? `ikdasm bin/TestDebug-net7.0/Java.Base-Tests.dll` showed that there were no `__RegisterNativeMembers()` methods emitted. The `jnimarshalmethod-gen` invocation was a no-op! The problems were twofold: 1. It was only looking for methods with `Android.Runtime.RegisterAttribute`. This was useful for Xamarin.Android (when we were trying to make it work), but doesn't work with Java.Base. We need to *also* look for `Java.Interop.JniMethodSignature`. Relatedly, the attempt to use `registerAttribute.Constructor.Parameters` to determine parameter names didn't work; the parameter name was always `""`. 2. A'la c93fea0, we need to ensure that the Java `native` methods we register are consistent with `jcw-gen` output. Fix these two problems, which allows `jnimarshalmethod-gen` to now emit marshal methods for types within `Java.Base-Tests.dll`. Additionally, rework the `jnimarshalmethod-gen -f` logic to *remove* the existing `__<$>_jni_marshal_methods` nested type when present.
1 parent 320636d commit 25850ba

File tree

2 files changed

+38
-30
lines changed

2 files changed

+38
-30
lines changed

build-tools/automation/templates/core-tests.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,26 @@ steps:
146146
continueOnError: true
147147
retryCountOnTaskFailure: 1
148148

149+
- task: DotNetCoreCLI@2
150+
displayName: 'jnimarshalmethod-gen Java.Base-Tests.dll'
151+
condition: or(eq('${{ parameters.runNativeDotnetTests }}', 'true'), eq('${{ parameters.runNativeTests }}', 'true'))
152+
inputs:
153+
command: custom
154+
custom: bin/$(Build.Configuration)$(NetCoreTargetFrameworkPathSuffix)/jnimarshalmethod-gen.dll
155+
arguments: bin/Test$(Build.Configuration)$(NetCoreTargetFrameworkPathSuffix)/Java.Base-Tests.dll -v -v --keeptemp
156+
continueOnError: true
157+
retryCountOnTaskFailure: 1
158+
159+
- task: DotNetCoreCLI@2
160+
displayName: 'Tests: Java.Base'
161+
condition: or(eq('${{ parameters.runNativeDotnetTests }}', 'true'), eq('${{ parameters.runNativeTests }}', 'true'))
162+
inputs:
163+
command: test
164+
testRunTitle: Java.Base ($(DotNetTargetFramework) - ${{ parameters.platformName }})
165+
arguments: bin/Test$(Build.Configuration)$(NetCoreTargetFrameworkPathSuffix)/Java.Base-Tests.dll
166+
continueOnError: true
167+
retryCountOnTaskFailure: 1
168+
149169
- task: DotNetCoreCLI@2
150170
displayName: 'Tests: java-source-utils'
151171
inputs:

tools/jnimarshalmethod-gen/App.cs

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -476,10 +476,14 @@ void CreateMarshalMethodAssembly (string path)
476476
continue;
477477

478478
var existingMarshalMethodsType = td.GetNestedType (TypeMover.NestedName);
479-
if (existingMarshalMethodsType != null && !forceRegeneration) {
480-
Warning (Message.WarningMarshalMethodsTypeAlreadyExists, existingMarshalMethodsType.GetAssemblyQualifiedName (cache), assemblyName);
479+
if (existingMarshalMethodsType != null) {
481480

482-
return;
481+
if (forceRegeneration) {
482+
td.NestedTypes.Remove (existingMarshalMethodsType);
483+
} else {
484+
Warning (Message.WarningMarshalMethodsTypeAlreadyExists, existingMarshalMethodsType.GetAssemblyQualifiedName (cache), assemblyName);
485+
return;
486+
}
483487
}
484488

485489
if (Verbose)
@@ -512,7 +516,7 @@ void CreateMarshalMethodAssembly (string path)
512516

513517
if (exportObj != null) {
514518
dynamic e = exportObj;
515-
name = e.Name;
519+
name = "n_" + methodName;
516520
signature = e.Signature;
517521
}
518522
else {
@@ -550,15 +554,14 @@ void CreateMarshalMethodAssembly (string path)
550554
Log (TraceLevel.Verbose, $"## Dumping contents of marshal method for `{td.FullName}::{method.Name}({string.Join (", ", method.GetParameters ().Select (p => p.ParameterType))})`:");
551555
Console.WriteLine (lambda.ToCSharpCode ());
552556
#endif // _DUMP_REGISTER_NATIVE_MEMBERS
553-
name = export?.Name ?? method.Name;
554557

555558
var mmDef = assemblyBuilder.Compile (lambda);
556559
mmDef.Name = name;
557560
mmTypeDef.Methods.Add (mmDef);
558561

559562
signature = export?.Signature ?? builder.GetJniMethodSignature (method);
560563

561-
registrations.Add (new ExpressionMethodRegistration ("n_" + method.Name, signature, mmDef));
564+
registrations.Add (new ExpressionMethodRegistration (name, signature, mmDef));
562565

563566
addedMethods.Add (methodName);
564567
}
@@ -739,35 +742,19 @@ public static MethodDefinition GetMethodDefinition (this TypeDefinition td, Meth
739742

740743
static bool CheckMethod (MethodDefinition m, ref string name, ref string methodName, ref string signature)
741744
{
742-
foreach (var registerAttribute in m.GetCustomAttributes ("Android.Runtime.RegisterAttribute")) {
745+
var registerAttrs = m.GetCustomAttributes ("Android.Runtime.RegisterAttribute")
746+
.Concat (m.GetCustomAttributes ("Java.Interop.JniMethodSignatureAttribute"));
747+
foreach (var registerAttribute in registerAttrs) {
743748
if (registerAttribute == null || !registerAttribute.HasConstructorArguments)
744749
continue;
745750

746-
var constructorParameters = registerAttribute.Constructor.Parameters.ToArray ();
747-
var constructorArguments = registerAttribute.ConstructorArguments.ToArray ();
748-
749-
for (int i = 0; i < constructorArguments.Length; i++) {
750-
switch (constructorParameters [i].Name) {
751-
case "name":
752-
name = constructorArguments [i].Value.ToString ();
753-
break;
754-
case "signature":
755-
signature = constructorArguments [i].Value.ToString ();
756-
break;
757-
}
758-
759-
}
760-
761-
if ((string.IsNullOrEmpty (name) || string.IsNullOrEmpty (signature)) && constructorArguments.Length != 3)
751+
if (registerAttribute.ConstructorArguments.Count < 2)
762752
continue;
763753

764-
if (string.IsNullOrEmpty (name))
765-
name = constructorArguments [0].Value.ToString ();
766-
767-
if (string.IsNullOrEmpty (signature))
768-
signature = constructorArguments [1].Value.ToString ();
754+
name = registerAttribute.ConstructorArguments [0].Value.ToString ();
755+
signature = registerAttribute.ConstructorArguments [1].Value.ToString ();
769756

770-
if (string.IsNullOrEmpty (name) || string.IsNullOrEmpty (signature))
757+
if ((string.IsNullOrEmpty (name) || string.IsNullOrEmpty (signature)))
771758
continue;
772759

773760
methodName = MarshalMemberBuilder.GetMarshalMethodName (name, signature);
@@ -808,13 +795,14 @@ public static bool NeedsMarshalMethod (this MethodDefinition md, DirectoryAssemb
808795
continue;
809796
}
810797

811-
for (int i = 0; i < ifaceMap.TargetMethods.Length; i++)
798+
for (int i = 0; i < ifaceMap.TargetMethods.Length; i++) {
812799
if (ifaceMap.TargetMethods [i] == method) {
813800
var imd = id.GetMethodDefinition (ifaceMap.InterfaceMethods [i]);
814801

815802
if (CheckMethod (imd, ref name, ref methodName, ref signature))
816803
return true;
817804
}
805+
}
818806
}
819807

820808
return false;

0 commit comments

Comments
 (0)