Beispiel #1
0
        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));
        }
Beispiel #2
0
        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),
            });
        }
Beispiel #3
0
 string GetJniMethodName(JavaCallableAttribute export, MethodInfo method)
 {
     return(export.Name ?? "n_" + method.Name);
 }
Beispiel #4
0
        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));
        }
Beispiel #5
0
        Delegate CreateJniMethodMarshaler(MethodInfo method, JavaCallableAttribute export, Type type)
        {
            var e = CreateMarshalToManagedExpression(method, export, type);

            return(e.Compile());
        }