diff --git a/external/Java.Interop b/external/Java.Interop
index 6bc87e8b55b..57f7bc849f3 160000
--- a/external/Java.Interop
+++ b/external/Java.Interop
@@ -1 +1 @@
-Subproject commit 6bc87e8b55bc00ae1423a5ae92cf5db573fc76ed
+Subproject commit 57f7bc849f36ec7c3159cc7729c7276b8dcd3ca4
diff --git a/src/Mono.Android/Android.Runtime/ExtraDelegates.cs b/src/Mono.Android/Android.Runtime/ExtraDelegates.cs
new file mode 100644
index 00000000000..26101d9a2ea
--- /dev/null
+++ b/src/Mono.Android/Android.Runtime/ExtraDelegates.cs
@@ -0,0 +1,30 @@
+// There are built-in delegates for these, but we no longer generate them in Mono.Android.dll
+// because bool is not a blittable type. But we still need them for pre-existing bindings.
+using System;
+
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PP_Z (IntPtr jnienv, IntPtr klass);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PPL_Z (IntPtr jnienv, IntPtr klass, IntPtr p0);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PPJ_Z (IntPtr jnienv, IntPtr klass, long p0);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate void _JniMarshal_PPLZ_V (IntPtr jnienv, IntPtr klass, IntPtr p0, bool p1);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PPLL_Z (IntPtr jnienv, IntPtr klass, IntPtr p0, IntPtr p1);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PPIL_Z (IntPtr jnienv, IntPtr klass, int p0, IntPtr p1);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PPLII_Z (IntPtr jnienv, IntPtr klass, IntPtr p0, int p1, int p2);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PPLLJ_Z (IntPtr jnienv, IntPtr klass, IntPtr p0, IntPtr p1, long p2);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PPLIL_Z (IntPtr jnienv, IntPtr klass, IntPtr p0, int p1, IntPtr p2);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PPLLL_Z (IntPtr jnienv, IntPtr klass, IntPtr p0, IntPtr p1, IntPtr p2);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate IntPtr _JniMarshal_PPIZI_L (IntPtr jnienv, IntPtr klass, int p0, bool p1, int p2);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate bool _JniMarshal_PPLZZL_Z (IntPtr jnienv, IntPtr klass, IntPtr p0, bool p1, bool p2, IntPtr p3);
+[global::System.Runtime.InteropServices.UnmanagedFunctionPointer (global::System.Runtime.InteropServices.CallingConvention.Winapi)]
+delegate void _JniMarshal_PPZIIII_V (IntPtr jnienv, IntPtr klass, bool p0, int p1, int p2, int p3, int p4);
diff --git a/src/Mono.Android/Mono.Android.csproj b/src/Mono.Android/Mono.Android.csproj
index 093a6d6a8ac..6c409057f53 100644
--- a/src/Mono.Android/Mono.Android.csproj
+++ b/src/Mono.Android/Mono.Android.csproj
@@ -96,6 +96,7 @@
+
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsClassifier.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsClassifier.cs
index 1507084dfc0..211baaf0948 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsClassifier.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsClassifier.cs
@@ -208,7 +208,7 @@ public bool Matches (MethodDefinition method)
return false;
}
- if (String.Compare (returnType, method.ReturnType.FullName, StringComparison.Ordinal) != 0) {
+ if (!TypeMatches (returnType, method.ReturnType.FullName)) {
log.LogWarning ($"Method '{method.FullName}' doesn't match native callback signature (invalid return type: expected '{returnType}', found '{method.ReturnType.FullName}')");
return false;
}
@@ -223,7 +223,7 @@ public bool Matches (MethodDefinition method)
parameterTypeName = pd.ParameterType.FullName;
}
- if (String.Compare (parameterTypeName, paramTypes[i], StringComparison.Ordinal) != 0) {
+ if (!TypeMatches (parameterTypeName, paramTypes[i])) {
log.LogWarning ($"Method '{method.FullName}' doesn't match native callback signature, expected parameter type '{paramTypes[i]}' at position {i}, found '{parameterTypeName}'");
return false;
}
@@ -231,6 +231,29 @@ public bool Matches (MethodDefinition method)
return true;
}
+
+ // Because these types are marshaled as different blittable types,
+ // we need to accept them as equivalent
+ static readonly (string Source, string Replacement)[] equivalent_types = [
+ (Source: "System.Boolean", Replacement: "System.SByte"),
+ (Source: "System.Char", Replacement: "System.UInt16"),
+ ];
+
+ static bool TypeMatches (string type, string methodType)
+ {
+ if (String.Compare (type, methodType, StringComparison.Ordinal) == 0)
+ return true;
+
+ foreach (var eq in equivalent_types) {
+ if (string.Compare (eq.Source, type, StringComparison.Ordinal) == 0 && string.Compare (eq.Replacement, methodType, StringComparison.Ordinal) == 0)
+ return true;
+
+ if (string.Compare (eq.Source, methodType, StringComparison.Ordinal) == 0 && string.Compare (eq.Replacement, type, StringComparison.Ordinal) == 0)
+ return true;
+ }
+
+ return false;
+ }
}
TypeDefinitionCache tdCache;