You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Context: #858
What do *I* want? To be able to use our wonderful Java binding
infrastructure against *Desktop Java*, not just Android.
At the same time, I don't want "Android-isms" "leaking" into such a
binding. *Just* Java.Interop, no xamarin-android.
"Take over" the `generator --codegen-target=JavaInterop1` format
so that it *isn't* useful for Xamarin.Android, and is instead usable
for non-Android usage.
This is a work-in-progress, and *far* from complete. For prototype
purposes, this *only* binds:
* `java.lang.Object`
* `java.lang.Throwable`
* `java.lang.Class`
The `Java.Base` binding is only for .NET 6 and above. I'm not
interested in .NET Standard support at this point in time.
Update `samples/Hello` so that it (1) works, and (2) instantiates the
`Java.Lang.Object` binding:
dotnet run --project samples/Hello
~~ Binding changes vs. Xamarin.Android ~~
Java arrays are bound as appropriate `IList<T>`, using the
`Java.Interop.Java*Array` types as an intermediary. This should help
reduce marshaling logic & overhead, as if the "source" array is a
`Java*Array`, it doesn't need to be "deep copied". The exception is
C# `params` arrays, which continue to be bound as arrays, and are
marshaled via an appropriate `Java*Array` type.
`java.io.InputStream` isn't bound as `System.IO.Stream`, etc.
"Java.Interop-style" constructors are used (25de1f3), e.g.
// This
DeclaringType (ref JniObjectReference reference, JniObjectReferenceOptions options);
// Not Xamarin.Android-style
DeclaringType (IntPtr handle, JniHandleOwnership transfer);
"Java.Interop-style" wrapper construction is used, e.g.
// This
var wrapper = JniEnvironment.Runtime.ValueManager.GetValue<DeclaringType>(ref h, JniObjectReferenceOptions.CopyAndDispose);
// Not this
var wrapper = Java.Lang.Object.GetObject<DeclaringType>(handle);
Marshal methods are currently skipped. Java-to-managed invocations
are not currently supported.
~~ TODO: Marshal Methods? ~~
Xamarin.Android uses Java Callable Wrappers + `Runtime.register()`
to specify which methods to register, via lots of reflection, etc.
For Desktop, JCW's shouldn't have all the methods to register.
Instead, use the `jnimarshalmethod-gen`-originated strategy of
`[JniAddNativeMethodRegistrationAttribute]` within the binding, and
then have it use `MarshalMethodBuilder` to generate the marshal
methods. Need to update `MarshalMethodBuilder` to look for overrides
in addition to methods with [`JavaCallable`], which in turn will
require an equivalent to `Android.Runtime.RegisterAttribute(…)`.
Perhaps `JniMethodSignatureAttribute(string name, string sig)`?
In the meantime, `Java.Base` will skip all marshal-method logic
plus runtime method generation. Leave that for later.
~~ Open Questions ~~
What's up with `java.lang.Class.getAnnotationsByType()`?
During an iteration of this PR, I got:
public unsafe Java.Interop.JavaObjectArray<Java.Lang.Object>? GetAnnotationsByType (Java.Lang.Class? annotationClass)
{
const string __id = "getAnnotationsByType.(Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;";
From `__id` we see that the Java return type is `Annotation[]`, yet
we bind it as an `Object` array? Why? How do we fix that to instead
bind it as `JavaObjectArray<Java.Lang.Annotations.Annotation>`?
Currently, it's differently *worse*; I don't know why, but `__id`
is now:
const string __id = "getAnnotationsByType.(Ljava/lang/Class;)[Ljava/lang/Object;";
i.e. the return type is an `Object` array instead of an `Annotation`
array, which is wrong, as per `javap`:
% javap -s java.lang.Class
…
public <A extends java.lang.annotation.Annotation> A getAnnotation(java.lang.Class<A>);
descriptor: (Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
Fixing unit tests...
0 commit comments