Example #1
0
        private static void LayoutUnmanagedSizeTest()
        {
            Console.WriteLine("running ValueTypeUnmanagedSizeTest...");

            foreach (string assemblyString in testAssemblies)
            {
                Assembly assembly = Assembly.Load(assemblyString);

                foreach (Type type in assembly.GetTypes())
                {
                    if (!type.IsAutoClass &&
                        type != typeof(void) &&
                        type != typeof(ArrayWithOffset) &&
                        type != typeof(HandleRef))
                    {
                        int size_reported_by_clr;

                        try
                        {
                            // will fail when CLR thinks the type has no layout
                            size_reported_by_clr = Marshal.SizeOf(type);
                        }
                        catch (Exception)
                        {
                            continue;
                        }

                        MarshalFlags flags = MarshalFlags.AnsiStrings | MarshalFlags.StructField;
                        if (runningOn64Bit)
                        {
                            flags |= MarshalFlags.Platform64Bit;
                        }

                        NativeType native_type = NativeType.FromClrType(type, flags);

                        if (native_type.TypeSize != size_reported_by_clr)
                        {
                            Console.WriteLine("* size mismatch for {0} (CLR {1}, tool {2})",
                                              type.FullName,
                                              size_reported_by_clr,
                                              native_type.TypeSize);
                        }
                    }
                }
            }
        }
Example #2
0
        private static void LayoutUnmanagedPrintoutTest()
        {
            string file_name = "_test.cpp";

            Console.WriteLine("running ValueTypeUnmanagedPrintoutTest...");

            // we'll generate a C++ source file with all the unmanaged structures
            // - it should compile
            // - the C++ sizeof operator should return the intended size
            // - the C++ offsetof macro should return the same offsets as Marshal.OffsetOf

            Console.WriteLine("  generating definitions...");

            using (TextWriterCodePrinter printer = new TextWriterCodePrinter(new StreamWriter(file_name)))
            {
                // prepare a memory printer to print main to
                CodeMemoryPrinter main_printer = new CodeMemoryPrinter();

                main_printer.PrintLn(OutputType.Other, "#define VERIFY(cond) if (!(cond)) printf(\"* \\\"%s\\\" violated\\n\", #cond)");

                main_printer.PrintLn(OutputType.Other, "int main()");
                main_printer.Print(OutputType.Other, "{");
                main_printer.Indent();
                main_printer.PrintLn();

                LogMemoryPrinter log_printer = new LogMemoryPrinter();

                printer.PrintLn(OutputType.Other, "#include <stddef.h>");
                printer.PrintLn(OutputType.Other, "#include <stdio.h>");
                printer.PrintLn(OutputType.Other, "#include <windows.h>");
                printer.PrintLn(OutputType.Other, "#include <oaidl.h>");

                printer.PrintLn();

                int counter = 0;
                foreach (string assemblyString in testAssemblies)
                {
                    Assembly assembly = Assembly.Load(assemblyString);

                    foreach (Type type in assembly.GetTypes())
                    {
                        if (!type.IsAutoClass)
                        {
                            int size_reported_by_clr;

                            try
                            {
                                // will fail when CLR thinks the type has no layout
                                size_reported_by_clr = Marshal.SizeOf(type);
                            }
                            catch (Exception)
                            {
                                continue;
                            }

                            MarshalFlags flags = MarshalFlags.AnsiStrings | MarshalFlags.StructField;
                            if (runningOn64Bit)
                            {
                                flags |= MarshalFlags.Platform64Bit;
                            }

                            NativeType        native_type     = NativeType.FromClrType(type, flags);
                            DefinedNativeType def_native_type = native_type as DefinedNativeType;

                            if (def_native_type != null)
                            {
                                // dump the "closure" of this definition to a namespace
                                string ns_name = String.Format("_CLR_{0}", counter++);

                                printer.PrintLn(OutputType.Other, "namespace " + ns_name);
                                printer.Print(OutputType.Other, "{");
                                printer.Indent();
                                printer.PrintLn();

                                NativeTypeDefinitionSet set = new NativeTypeDefinitionSet();
                                set.Add(def_native_type.Definition);
                                def_native_type.Definition.GetDefinitionsRecursive(set, def_native_type.Definition);

                                // enumerate the closure (will respect dependencies and return definitions
                                // in a correct order introducing forward declarations if necessary)
                                foreach (NativeTypeDefinition def in set)
                                {
                                    def.PrintTo(printer, log_printer,
                                                //PrintFlags.UsePlainC |
                                                PrintFlags.UseDefinedComInterfaces |
                                                PrintFlags.MangleEnumFields);

                                    printer.PrintLn();
                                    printer.PrintLn();
                                }

                                printer.Unindent();
                                printer.PrintLn();
                                printer.PrintLn(OutputType.Other, "};");

                                // add tests to main()
                                main_printer.PrintLn(OutputType.Other, String.Format(
                                                         "VERIFY(sizeof({0}::{1}) == {2});",
                                                         ns_name,
                                                         def_native_type.Definition.Name,
                                                         size_reported_by_clr));

                                StructureDefinition struct_def = def_native_type.Definition as StructureDefinition;
                                if (struct_def != null)
                                {
                                    for (int i = 0; i < struct_def.FieldCount; i++)
                                    {
                                        NativeField nf = struct_def.GetField(i);

                                        int offset;
                                        try
                                        {
                                            offset = (int)Marshal.OffsetOf(type, nf.Name);
                                        }
                                        catch (Exception)
                                        {
                                            continue;
                                        }

                                        // if we think we know the offset of this field, we will verify it
                                        main_printer.PrintLn(OutputType.Other, String.Format(
                                                                 "VERIFY(offsetof({0}::{1}, {2}) == {3});",
                                                                 ns_name,
                                                                 def_native_type.Definition.Name,
                                                                 nf.Name,
                                                                 offset));
                                    }
                                }
                            }
                        }
                    }
                }

                main_printer.Print(OutputType.Other, "return 0;");
                main_printer.Unindent();
                main_printer.PrintLn();
                main_printer.PrintLn(OutputType.Other, "}");

                main_printer.ReplayTo(printer);
            }

            Console.WriteLine("  compiling the generated file...");

            ProcessStartInfo start_info = new ProcessStartInfo(
                @"c:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\cl.exe", "/DUNICODE " + file_name);

            start_info.WorkingDirectory       = Directory.GetCurrentDirectory();
            start_info.UseShellExecute        = false;
            start_info.CreateNoWindow         = true;
            start_info.RedirectStandardOutput = true;

            Process cl_proc = Process.Start(start_info);

            cl_proc.WaitForExit();

            Console.WriteLine(cl_proc.StandardOutput.ReadToEnd());

            Console.WriteLine("  running the generated executable...");

            start_info.FileName  = Path.ChangeExtension(file_name, ".exe");
            start_info.Arguments = String.Empty;

            Process tst_proc = Process.Start(start_info);

            tst_proc.WaitForExit();

            Console.WriteLine(tst_proc.StandardOutput.ReadToEnd());
        }