Exemple #1
0
        public StructureNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc.Type.IsValueType || desc.IsStructField)
            {
                // the only allowed UnmanagedType is Struct
                ValidateUnmanagedType(desc, MarshalType.Struct);
            }
            else
            {
                // the only allowed UnmanagedType is LPStruct
                ValidateUnmanagedType(desc, MarshalType.Class);

                // if it's not byref, then it goes in-only by default
                if (++this.indirections == 1)
                {
                    byDefaultInOnly = true;
                }
            }

            if (desc.MarshalAs != null)
            {
                // warn against explicit MarshalAsAttribute on a normalized structure
                Type marshal_type = Utility.GetNormalizedType(desc.Type);
                if (marshal_type != desc.Type)
                {
                    Log.Add(Errors.WARN_NormalizedStructure, desc.Type.FullName, marshal_type.FullName);
                }
            }

            if (!Utility.HasLayout(desc.Type))
            {
                Log.Add(Errors.ERROR_TypeHasNoLayout, desc.Type.FullName);
            }

            StructureDefinition struct_def = StructureDefinition.Get(desc);

            if (this.indirections == 1 && desc.PointerIndirections == 0)
            {
                // either byval class or byref struct
                ExplainPinningOrCopying(desc, struct_def.IsBlittable);
            }
            else if (this.indirections == 2 && desc.PointerIndirections == 0)
            {
                // byref class - double indirected
                ExplainMemoryManagement(desc,
                                        struct_def.IsUnion ? Resources._Union : Resources._Structure);
            }

            this.typeDefinition = struct_def;
            this.nameModifier   = (struct_def.IsUnion ? UnionModifier : StructModifier);
        }
Exemple #2
0
 public ForwardDeclaration(StructureDefinition definition)
 {
     Debug.Assert(definition != null);
     this.definition = definition;
 }
Exemple #3
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());
        }