mono / Embeddinator-4000

Tools to turn .NET libraries into native libraries that can be consumed on Android, iOS, Mac, Linux and other platforms.
MIT License
758 stars 95 forks source link

[Android] Support array types for Java.Lang.Object types #523

Open Zomb opened 6 years ago

Zomb commented 6 years ago

If I use an array as an argument for a C# method, for example:

[Export("parseData")]
public void ParseData(byte[] vendorData)

or

[Export("parseData")]
public void ParseData(int[] vendorData)

e4k completes successfully and generates the aar. Once I include it in my AS project and run the app, I get the following exception. I am using primitives as my type, so I am not sure what is causing the issue.

E/mono: Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NotSupportedException: Only primitive types and IJavaObject is supported in array type in callback method parameter or return value at Java.Interop.DynamicInvokeTypeInfo.GetCallbackCleanup (System.Type type, Mono.CodeGeneration.CodeExpression arg, Mono.CodeGeneration.CodeExpression orgArg) [0x00031] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicInvokeTypeInfo.CleanupCallback (Mono.CodeGeneration.CodeExpression arg, Mono.CodeGeneration.CodeExpression orgArg) [0x00000] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicCallbackCodeGenerator.GenerateNativeCallbackDelegate (System.String generatedMethodName) [0x00219] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicCallbackCodeGenerator.GenerateNativeCallbackDelegate () [0x0009b] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicCallbackCodeGenerator.GetCallback () [0x00008] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicCallbackCodeGenerator.Create (System.Reflection.MethodInfo method) [0x00006] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in <8a9b47e6e83b4973b835cda3f53125a0>:0 --- End of inner exception stack trace --- at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0004b] in <8a9b47e6e83b4973b835cda3f53125a0>:0 at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <8a9b47e6e83b4973b835cda3f53125a0>:0 at Android.Runtime.JNIEnv.CreateDynamicCallback (System.Reflection.MethodInfo method) [0x00070] in :0 at Android.Runtime.JNIEnv.RegisterJniNatives (System.IntPtr typeName_ptr, System.Int32 typeName_len, System.IntPtr jniClass, System.IntPtr methods_ptr, System.Int32 methods_len) [0x001b1] in :0 E/mono-rt: [ERROR] FATAL UNHANDLED EXCEPTION: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NotSupportedException: Only primitive types and IJavaObject is supported in array type in callback method parameter or return value at Java.Interop.DynamicInvokeTypeInfo.GetCallbackCleanup (System.Type type, Mono.CodeGeneration.CodeExpression arg, Mono.CodeGeneration.CodeExpression orgArg) [0x00031] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicInvokeTypeInfo.CleanupCallback (Mono.CodeGeneration.CodeExpression arg, Mono.CodeGeneration.CodeExpression orgArg) [0x00000] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicCallbackCodeGenerator.GenerateNativeCallbackDelegate (System.String generatedMethodName) [0x00219] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicCallbackCodeGenerator.GenerateNativeCallbackDelegate () [0x0009b] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicCallbackCodeGenerator.GetCallback () [0x00008] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at Java.Interop.DynamicCallbackCodeGenerator.Create (System.Reflection.MethodInfo method) [0x00006] in <33a53599dc2a4aa68ea5304041ec3a65>:0 at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in <8a9b47e6e83b4973b835cda3f53125a0>:0 --- End of inner exception stack trace --- at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0004b] in <8a9b47e6e83b4973b835cda3f53125a0>:0 at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <8a9b47e6e83b4973b835cda3f53125a0>:0 at Android.Runtime.JNIEnv.CreateDynamicCallback (System.Reflection.MethodInfo method) [0x00070] in :0 at Android.Runtime.JNIEnv.RegisterJniNatives (System.IntPtr typeName_ptr, System.Int32 typeName_len, System.IntPtr jniClass, System.IntPtr methods_ptr, System.Int32 methods_len) [0x001b1] in :0

tritao commented 6 years ago

Hey, arrays are still not supported in Java. It's the next feature to be supported (PR https://github.com/mono/Embeddinator-4000/pull/508).

Zomb commented 6 years ago

Great! My current workaround for anyone else who runs into this right now is convert the array into a Base64String and back again.

var fromBase64String = Convert.FromBase64String(data);

tritao commented 6 years ago

Actually, looking again at the stack trace, this error seems related to arrays in Java.Lang.Object derived types, right? If that's the case, then my PR only implements support for non-Java.Lang.Object derived C# types.

Zomb commented 6 years ago

Yes, the C# class that contains this derives from Java.Lang.Object because it needs to run on a background thread, and that's the only way to make that work according to @jonathanpeppers as documented in #439. Would this be a bug then? Or a new feature request?

tritao commented 6 years ago

I changed the title to track the issue more accurately. Not sure when this might be fixed though because it's not a limitation of Embeddinator generator itself but of the interop generator from Xamarin.Android.

Zomb commented 6 years ago

Okay! In the change that you made, you said 'non-primitive array types' but I am running into the issue when my array is of type byte or int. I haven't tried using non-primitive types in an array.

tritao commented 6 years ago

I was going through the exception message in the trace you posted: Only primitive types and IJavaObject is supported in array type in callback method parameter or return value.

Maybe this is not accurate after all?

Zomb commented 6 years ago

Yes, it says primitive types are allowed, but when I use a primitive type it errors out, and I was not sure why.

jonathanpeppers commented 6 years ago

@Zomb I'll try this out next week and write a test for it. I vaguely remember seeing something that was fixed in this area in Xamarin.Android.

So updating Xamarin.Android might fix it:

Of course if it's still broken on XA master, I can ask the right people.

mfkl commented 6 years ago

Any news about this? Any workaround?

I get the same message on Xamarin.Android Only primitive types and IJavaObject is supported in array type in callback method parameter or return value. Need to expose a method that has an array of float as parameter.

Thanks!