Skip to content

Commit

Permalink
[marshal methods] Properly support arrays of arrays (#7707)
Browse files Browse the repository at this point in the history
Fixes: #7693

Java code similar to:

	package com.xamarin.android;

	public interface DataListener {
	  void onDataReceived (
	      java.lang.String fromNode,
	      java.lang.String fromChannel,
	      java.lang.String payloadType,
	      byte[][] payload);
	}

Generates a Java JNI signature with multiple `[`s:

	(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[[B)V

which then would throw our marshal methods native assembly generator
off, because it didn't expect that there might be consecutive `[`
characters for parameters which are arrays of arrays (of any rank):

	System.InvalidOperationException: Unsupported JNI array type '[' at index 56 of signature '(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[[B)V'
	error XAGPM7009:    at Xamarin.Android.Tasks.MarshalMethodsNativeAssemblyGenerator.<ParseJniSignature>g__JniTypeToManaged|55_0(Char jniType, <>c__DisplayClass55_0&)
	error XAGPM7009:    at Xamarin.Android.Tasks.MarshalMethodsNativeAssemblyGenerator.ParseJniSignature(String signature, MethodDefinition implementedMethod)
	error XAGPM7009:    at Xamarin.Android.Tasks.MarshalMethodsNativeAssemblyGenerator.ProcessAndAddMethod(List`1 allMethods, MarshalMethodEntry entry, Boolean useFullNativeSignature, Dictionary`2 seenClasses, Dictionary`2 overloadedNativeSymbolNames)
	error XAGPM7009:    at Xamarin.Android.Tasks.MarshalMethodsNativeAssemblyGenerator.Init()
	error XAGPM7009:    at Xamarin.Android.Tasks.GeneratePackageManagerJava.AddEnvironment()
	error XAGPM7009:    at Xamarin.Android.Tasks.GeneratePackageManagerJava.RunTask()
	error XAGPM7009:    at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/builder/azdo/_work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:line 17

Fix this by skipping over the "extra" `[` characters.  This generates
code which uses a simple pointer to array, instead of a pointer to
pointer etc.  We can take this shortcut because we don't dereference
the parameter in our generated code in any way, instead passing it
as-is to the managed code.
  • Loading branch information
grendello authored Jan 20, 2023
1 parent 164e799 commit baa5a73
Showing 1 changed file with 7 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,13 @@ string MangleForJni (string name)
}

if (jniType == '[') {
idx++;
// Arrays of arrays (any rank) are bound as a simple pointer, which makes the generated code much simpler (no need to generate pointers to
// pointers to pointers etc), especially that we don't need to dereference these pointers in generated code, we simply pass them along to
// the managed land after all.
while (signature[idx] == '[') {
idx++;
}

jniType = signature[idx];
if (jniArrayTypeMap.TryGetValue (jniType, out managedType)) {
if (jniType == 'L') {
Expand Down

0 comments on commit baa5a73

Please sign in to comment.