Example #1
0
        void CreateMarshalMethodAssembly(string path)
        {
            var assembly = Assembly.LoadFile(Path.GetFullPath(path));

            var baseName     = Path.GetFileNameWithoutExtension(path);
            var assemblyName = new AssemblyName(baseName + "-JniMarshalMethods");
            var fileName     = assemblyName.Name + ".dll";
            var destDir      = string.IsNullOrEmpty(outDirectory) ? Path.GetDirectoryName(path) : outDirectory;
            var builder      = CreateExportedMemberBuilder();
            var matchType    = typeNameRegexes.Count > 0;

            if (Verbose)
            {
                ColorWriteLine($"Preparing marshal method assembly '{assemblyName}'", ConsoleColor.Cyan);
            }

            var da = AppDomain.CurrentDomain.DefineDynamicAssembly(
                assemblyName,
                AssemblyBuilderAccess.Save,
                destDir);

            var dm = da.DefineDynamicModule("<default>", fileName);

            var ad = resolver.GetAssembly(path);

            PrepareTypeMap(ad.MainModule);

            Type[] types = null;
            try {
                types = assembly.GetTypes();
            } catch (ReflectionTypeLoadException e) {
                types = e.Types;
                foreach (var le in e.LoaderExceptions)
                {
                    Warning($"Type Load exception{Environment.NewLine}{le}");
                }
            }

            foreach (var systemType in types)
            {
                if (systemType == null)
                {
                    continue;
                }

                var type = systemType.GetTypeInfo();

                if (matchType)
                {
                    var matched = false;

                    foreach (var r in typeNameRegexes)
                    {
                        matched |= r.IsMatch(type.FullName);
                    }

                    if (!matched)
                    {
                        continue;
                    }
                }

                if (type.IsInterface || type.IsGenericType || type.IsGenericTypeDefinition)
                {
                    continue;
                }

                var td = FindType(type);

                if (td == null)
                {
                    if (Verbose)
                    {
                        Warning($"Unable to find cecil's TypeDefinition of type {type}");
                    }
                    continue;
                }
                if (!td.ImplementsInterface("Java.Interop.IJavaPeerable", cache))
                {
                    continue;
                }

                var existingMarshalMethodsType = td.GetNestedType(TypeMover.NestedName);
                if (existingMarshalMethodsType != null && !forceRegeneration)
                {
                    Warning($"Marshal methods type '{existingMarshalMethodsType.GetAssemblyQualifiedName (cache)}' already exists. Skipped generation of marshal methods in assembly '{assemblyName}'. Use -f to force regeneration when desired.");

                    return;
                }

                if (Verbose)
                {
                    ColorWriteLine($"Processing {type} type", ConsoleColor.Yellow);
                }

                var         registrationElements = new List <Expression> ();
                var         targetType           = Expression.Variable(typeof(Type), "targetType");
                TypeBuilder dt = null;

                var flags = BindingFlags.Public | BindingFlags.NonPublic |
                            BindingFlags.Instance | BindingFlags.Static;

                var methods = type.GetMethods(flags);
                Array.Sort(methods, new MethodsComparer(type, td));

                addedMethods.Clear();

                foreach (var method in methods)
                {
                    // TODO: Constructors
                    var    export     = method.GetCustomAttribute <JavaCallableAttribute> ();
                    string signature  = null;
                    string name       = null;
                    string methodName = method.Name;

                    if (export == null)
                    {
                        if (method.IsGenericMethod || method.ContainsGenericParameters || method.IsGenericMethodDefinition || method.ReturnType.IsGenericType)
                        {
                            continue;
                        }

                        if (method.DeclaringType != type)
                        {
                            continue;
                        }

                        var md = td.GetMethodDefinition(method);

                        if (md == null)
                        {
                            if (Verbose)
                            {
                                Warning($"Unable to find cecil's MethodDefinition of method {method}");
                            }
                            continue;
                        }

                        if (!md.NeedsMarshalMethod(resolver, cache, method, ref name, ref methodName, ref signature))
                        {
                            continue;
                        }
                    }

#if !_ALL_THE_ARGUMENTS
                    if (method.GetParameters().Length > 14)
                    {
                        Warning($"Methods taking more than 14 parameters is not supported.");
                        continue;
                    }
#endif  // !_ALL_THE_ARGUMENTS

                    if (dt == null)
                    {
                        dt = GetTypeBuilder(dm, type);
                    }

                    if (addedMethods.Contains(methodName))
                    {
                        continue;
                    }

                    if (Verbose)
                    {
                        Console.Write("Adding marshal method for ");
                        ColorWriteLine($"{method}", ConsoleColor.Green);
                    }

                    var mb = dt.DefineMethod(
                        methodName,
                        System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Static);

                    var lambda = builder.CreateMarshalToManagedExpression(method);
                    lambda.CompileToMethod(mb);

                    if (export != null)
                    {
                        name      = export.Name;
                        signature = export.Signature;
                    }

                    if (signature == null)
                    {
                        signature = builder.GetJniMethodSignature(method);
                    }

                    registrationElements.Add(CreateRegistration(name, signature, lambda, targetType, methodName));

                    addedMethods.Add(methodName);
                }
                if (dt != null)
                {
                    AddRegisterNativeMembers(dt, targetType, registrationElements);
                }
            }

            foreach (var tb in definedTypes)
            {
                tb.Value.CreateType();
            }

            da.Save(fileName);

            if (Verbose)
            {
                ColorWriteLine($"Marshal method assembly '{assemblyName}' created", ConsoleColor.Cyan);
            }

            resolver.SearchDirectories.Add(destDir);
            var dstAssembly = resolver.GetAssembly(fileName);

            if (!string.IsNullOrEmpty(outDirectory))
            {
                path = Path.Combine(outDirectory, Path.GetFileName(path));
            }

            var mover = new TypeMover(dstAssembly, ad, path, definedTypes, resolver, cache);
            mover.Move();

            if (!keepTemporary)
            {
                FilesToDelete.Add(dstAssembly.MainModule.FileName);
            }
        }
Example #2
0
        void CreateMarshalMethodAssembly(string path)
        {
            var assembly = Assembly.LoadFile(path);

            var baseName     = Path.GetFileNameWithoutExtension(path);
            var assemblyName = new AssemblyName(baseName + "-JniMarshalMethods");
            var destPath     = assemblyName.Name + ".dll";
            var builder      = CreateExportedMemberBuilder();
            var matchType    = typeNameRegexes.Count > 0;

            if (Verbose)
            {
                ColorWriteLine($"Preparing marshal method assembly '{assemblyName}'", ConsoleColor.Cyan);
            }

            var da = AppDomain.CurrentDomain.DefineDynamicAssembly(
                assemblyName,
                AssemblyBuilderAccess.Save,
                Path.GetDirectoryName(path));

            var dm = da.DefineDynamicModule("<default>", destPath);

            var ad = resolver.GetAssembly(path);

            foreach (var type in assembly.DefinedTypes)
            {
                if (matchType)
                {
                    var matched = false;

                    foreach (var r in typeNameRegexes)
                    {
                        matched |= r.IsMatch(type.FullName);
                    }

                    if (!matched)
                    {
                        continue;
                    }
                }

                if (type.IsGenericType || type.IsGenericTypeDefinition)
                {
                    continue;
                }

                var td = ad.MainModule.FindType(type);

                if (td == null)
                {
                    if (Verbose)
                    {
                        Warning($"Unable to find cecil's TypeDefinition of type {type}");
                    }
                    continue;
                }
                if (!td.ImplementsInterface("Java.Interop.IJavaPeerable"))
                {
                    continue;
                }

                var existingMarshalMethodsType = td.GetNestedType(TypeMover.NestedName);
                if (existingMarshalMethodsType != null && !forceRegeneration)
                {
                    Warning($"Marshal methods type '{existingMarshalMethodsType.GetAssemblyQualifiedName ()}' already exists. Skipped generation of marshal methods. Use -f to force regeneration when desired.");

                    continue;
                }

                var         registrationElements = new List <Expression> ();
                var         targetType           = Expression.Variable(typeof(Type), "targetType");
                TypeBuilder dt = null;

                var flags = BindingFlags.Public | BindingFlags.NonPublic |
                            BindingFlags.Instance | BindingFlags.Static;
                foreach (var method in type.GetMethods(flags))
                {
                    // TODO: Constructors
                    var    export     = method.GetCustomAttribute <JavaCallableAttribute> ();
                    string signature  = null;
                    string name       = null;
                    string methodName = method.Name;

                    if (export == null)
                    {
                        if (method.IsGenericMethod || method.ContainsGenericParameters || method.IsGenericMethodDefinition || method.ReturnType.IsGenericType)
                        {
                            continue;
                        }

                        if (method.DeclaringType != type)
                        {
                            continue;
                        }

                        var md = td.GetMethodDefinition(method);

                        if (md == null)
                        {
                            if (Verbose)
                            {
                                Warning($"Unable to find cecil's MethodDefinition of method {method}");
                            }
                            continue;
                        }

                        if (!md.NeedsMarshalMethod(resolver, method, ref name, ref methodName, ref signature))
                        {
                            continue;
                        }
                    }

                    if (dt == null)
                    {
                        dt = GetTypeBuilder(dm, type);
                    }

                    if (Verbose)
                    {
                        Console.Write("Adding marshal method for ");
                        ColorWriteLine($"{method}", ConsoleColor.Green);
                    }

                    var mb = dt.DefineMethod(
                        methodName,
                        System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Static);

                    var lambda = builder.CreateMarshalToManagedExpression(method);
                    lambda.CompileToMethod(mb);

                    if (export != null)
                    {
                        name      = export.Name;
                        signature = export.Signature;
                    }

                    if (signature == null)
                    {
                        signature = builder.GetJniMethodSignature(method);
                    }

                    registrationElements.Add(CreateRegistration(name, signature, lambda, targetType, methodName));
                }
                if (dt != null)
                {
                    AddRegisterNativeMembers(dt, targetType, registrationElements);
                }
            }

            foreach (var tb in definedTypes)
            {
                tb.Value.CreateType();
            }

            da.Save(destPath);

            if (Verbose)
            {
                ColorWriteLine($"Marshal method assembly '{assemblyName}' created", ConsoleColor.Cyan);
            }

            var dstAssembly = resolver.GetAssembly(destPath);
            var mover       = new TypeMover(dstAssembly, ad, definedTypes, resolver);

            mover.Move();

            if (!keepTemporary)
            {
                FilesToDelete.Add(dstAssembly.MainModule.FileName);
            }

            definedTypes.Clear();
        }