public string GetJniMethodSignature(JavaCallableAttribute export, MethodInfo method) { if (export == null) { throw new ArgumentNullException("export"); } if (method == null) { throw new ArgumentNullException("method"); } if (export.Signature != null) { return(export.Signature); } return(export.Signature = GetJniMethodSignature(method)); }
public JniNativeMethodRegistration CreateMarshalToManagedMethodRegistration(JavaCallableAttribute export, MethodInfo method, Type type = null) { if (export == null) { throw new ArgumentNullException("export"); } if (method == null) { throw new ArgumentNullException("method"); } string signature = GetJniMethodSignature(export, method); return(new JniNativeMethodRegistration() { Name = GetJniMethodName(export, method), Signature = signature, Marshaler = CreateJniMethodMarshaler(method, export, type), }); }
string GetJniMethodName(JavaCallableAttribute export, MethodInfo method) { return(export.Name ?? "n_" + method.Name); }
public LambdaExpression CreateMarshalToManagedExpression(MethodInfo method, JavaCallableAttribute callable, Type type = null) { if (method == null) { throw new ArgumentNullException("method"); } type = type ?? method.DeclaringType; var methodParameters = method.GetParameters(); CheckMarshalTypesMatch(method, callable?.Signature, methodParameters); bool direct = IsDirectMethod(methodParameters); var jnienv = Expression.Parameter(typeof(IntPtr), direct ? methodParameters [0].Name : "__jnienv"); var context = Expression.Parameter(typeof(IntPtr), direct ? methodParameters [1].Name : (method.IsStatic ? "__class" : "__this")); var envp = Expression.Variable(typeof(JniTransition), "__envp"); var jvm = Expression.Variable(typeof(JniRuntime), "__jvm"); var vm = Expression.Variable(typeof(JniRuntime.JniValueManager), "__vm"); var envpVars = new List <ParameterExpression> () { envp, jvm, }; int peerableParametersCount = 0; for (int i = 0; i < methodParameters.Length; ++i) { var marshaler = GetParameterMarshaler(methodParameters [i]); if (typeof(IJavaPeerable).GetTypeInfo().IsAssignableFrom(methodParameters [i].ParameterType.GetTypeInfo())) { peerableParametersCount++; } } bool useVmVariable = (!method.IsStatic || peerableParametersCount > 0) && !direct; if (useVmVariable) { envpVars.Add(vm); } var envpBody = new List <Expression> () { Expression.Assign(envp, CreateJniTransition(jnienv)), }; var waitForGCBridge = typeof(JniRuntime.JniValueManager) .GetRuntimeMethod(nameof(JniRuntime.JniValueManager.WaitForGCBridgeProcessing), new Type [0]); var marshalBody = new List <Expression> () { Expression.Assign(jvm, GetRuntime()), }; if (useVmVariable) { marshalBody.Add(Expression.Assign(vm, Expression.Property(jvm, "ValueManager"))); marshalBody.Add(Expression.Call(vm, waitForGCBridge)); } else { marshalBody.Add(Expression.Call(Expression.Property(jvm, "ValueManager"), waitForGCBridge)); } Expression self = null; var marshalerContext = new JniValueMarshalerContext(jvm, useVmVariable ? vm : null); if (!method.IsStatic) { var selfMarshaler = Runtime.ValueManager.GetValueMarshaler(type); self = selfMarshaler.CreateParameterToManagedExpression(marshalerContext, context, 0, type); } var marshalParameters = new List <ParameterExpression> (methodParameters.Length); var invokeParameters = new List <Expression> (methodParameters.Length); for (int i = 0; i < methodParameters.Length; ++i) { var marshaler = GetParameterMarshaler(methodParameters [i]); ParameterExpression np; if (i > 1 || !direct) { np = Expression.Parameter(marshaler.MarshalType, methodParameters [i].Name); } else { if (i == 0) { np = jnienv; } else if (i == 1) { np = context; } else { throw new InvalidOperationException("Should not be reached."); } } var p = marshaler.CreateParameterToManagedExpression(marshalerContext, np, methodParameters [i].Attributes, methodParameters [i].ParameterType); marshalParameters.Add(np); invokeParameters.Add(p); } marshalBody.AddRange(marshalerContext.CreationStatements); Expression invoke = method.IsStatic ? Expression.Call(method, invokeParameters) : Expression.Call(self, method, invokeParameters); Expression ret = null; if (method.ReturnType == typeof(void)) { envpVars.AddRange(marshalerContext.LocalVariables); marshalBody.Add(invoke); envpBody.Add( Expression.TryCatchFinally( Expression.Block(marshalBody), CreateDisposeJniEnvironment(envp, marshalerContext.CleanupStatements), CreateMarshalException(envp, jvm, null))); } else { var rmarshaler = GetParameterMarshaler(method.ReturnParameter); var jniRType = rmarshaler.MarshalType; var exit = Expression.Label(jniRType, "__exit"); var mret = Expression.Variable(method.ReturnType, "__mret"); envpVars.Add(mret); marshalBody.Add(Expression.Assign(mret, invoke)); marshalerContext.CreationStatements.Clear(); ret = rmarshaler.CreateReturnValueFromManagedExpression(marshalerContext, mret); marshalBody.AddRange(marshalerContext.CreationStatements); marshalBody.Add(Expression.Return(exit, ret)); envpVars.AddRange(marshalerContext.LocalVariables); envpBody.Add( Expression.TryCatchFinally( Expression.Block(marshalBody), CreateDisposeJniEnvironment(envp, marshalerContext.CleanupStatements), CreateMarshalException(envp, jvm, exit))); envpBody.Add(Expression.Label(exit, Expression.Default(jniRType))); } var funcTypeParams = new List <Type> (); var bodyParams = new List <ParameterExpression> (); if (!direct) { funcTypeParams.Add(typeof(IntPtr)); funcTypeParams.Add(typeof(IntPtr)); bodyParams.Add(jnienv); bodyParams.Add(context); } foreach (var p in marshalParameters) { funcTypeParams.Add(p.Type); } var marshalerType = GetMarshalerType(ret?.Type, funcTypeParams, method.DeclaringType); bodyParams.AddRange(marshalParameters); var body = Expression.Block(envpVars, envpBody); return(marshalerType == null ? Expression.Lambda(body, bodyParams) : Expression.Lambda(marshalerType, body, bodyParams)); }
Delegate CreateJniMethodMarshaler(MethodInfo method, JavaCallableAttribute export, Type type) { var e = CreateMarshalToManagedExpression(method, export, type); return(e.Compile()); }