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
Fixes: dotnet#8
Extend the JniValueMarshaler abstraction from commit 77a6bf8 so that
JniValueMarshaler can *also* marshal from/to Java via
System.Linq.Expressions expression trees:
partial class JniValueMarshaler {
public virtual Type MarshalType {get;}
public virtual Expression CreateParameterToManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize, Type targetType);
public virtual Expression CreateParameterFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue, ParameterAttributes synchronize);
public virtual Expression CreateReturnValueFromManagedExpression (JniValueMarshalerContext context, ParameterExpression sourceValue);
}
The members:
* MarshalType: The JNI type that this marshaler marshals from/to.
The default value is typeof(IntPtr), making it suitable for
marshaling reference types.
* CreateParameterToManagedExpression():
Java > Managed marshaler.
Convert the Java parameter `sourceValue`, of type `MarshalType`,
to the managed type `targetType`.
* CreateParameterFromManagedExpression():
Managed > Java marshaler.
Convert the managed parameter `sourceValue` to `MarshalType`.
* CreateReturnValueFromManagedExpression():
Managed > Java marshaler, for return values (not parameters).
Convert the managed parameter `sourceValue` to `MarshalType`,
suitable for use when returning to Java.
The default implementation of these methods uses the marshaling
behavior provided by the abstract JniValueMarshaler.CreateValue(),
JniValueMarshaler.CreateArgumentState(), and
JniValueMarshaler.DestroyArgumentState() methods.
CreateParameterToManagedExpression() uses CreateValue(), while
CreateParameterFromManagedExpression() and
CreateReturnValueFromManagedExpression() uses both
CreateArgumentState() and DestroyArgumentState() to marshal values.
The purpose of using expression trees is to permit optimizations:
Java.Interop.ExportedMemberBuilder uses expression trees in order to
generate the Java > Managed marshaling code, so by extending
JniValueMarshaler to use expression trees it's possible to use a
smarter marshaling algorithm for specific types.
For example, the builtin types don't need to do *anything*, as they're
binary compatible with the JNI types. Conseequently, they only need to
return the source parameter, instead of actually using
JniValueManager.CreateValue()/etc.
Similarly, the IJavaPeerable value marshaler can directly use
JniRuntime.JniValueManager.GetValue<T>() for Java > managed marshaling
and IJavaPeerable.PeerReference for Managed > Java marshaling.
Finally, this doesn't *fully* fix Issue dotnet#8, but it fixes "enough" to
close the issue. What's missing, but can be done later, is:
> Do in conjunction w/ Java.Interop.Dynamic
While Java.Interop.Dynamic can (should!) use
JniValueManager.CreateParameterFromManagedExpression(), it doesn't
currently because it doesn't even perform the JNI invocation via
expression trees; it uses expression trees to invoke the intermediate
helper method JavaClassInfo.TryInvokeMember().
This can be fixed, but doesn't need to be done yet.
> Need to permit use of custom attributes on return types, parameter
> types, "inline" into marshal methods.
This will be done in a separate commit for a JniValueManagerAttribute
custom attribute. (Let's try to keep commits single purpose, right?)
> Use Expression<TDelegate> to make it easier to write marshalers.
This isn't needed for the currently supported marshalers.
0 commit comments