Example #1
0
 public void GenerateForwardTypeDefinition(IndentedBuilder builder)
 {
     builder.AppendIndented(TypeDef.TypeDefinitionStr());
     if (TypeDef.IsEnum)
     {
         builder.Append(" : ");
         builder.Append(TypeDef.GetEnumUnderlyingType().ParsedTypeSignatureStr());
     }
     builder.Append(";");
     builder.AppendNewLine();
 }
Example #2
0
 public void GenerateImplementation(IndentedBuilder builder)
 {
     foreach (MethodDef m in TypeDef.Methods.Where(m => (!m.IsVirtual || !m.IsInterfacedMethod()) && m.Name != "op_Explicit" && m.Name != "op_Implicit"))
     {
         object rva = m.GetRva();
         if (!m.HasGenericParameters && rva != null)
         {
             string rst = m.ImplementationStr(rva).Replace("{", "\n{\n\t");
             rst = rst.Replace(";", ";\n\t");
             rst = rst.Replace("	 }", "}\n");
             builder.AppendIndentedLine(rst.Trim() + Environment.NewLine);
         }
     }
 }
Example #3
0
        public SdkGenerator(ModuleDefMD module, IAssembly corlib)
        {
            Console.WriteLine("generating types for: " + module);

            var visitedTypes = new HashSet <TypeDef>();
            var toVisit      = new Deque <TypeDef>();

            foreach (var type in module.Types)
            {
                toVisit.AddToBack(type);
            }

            if (module.Name.Contains("mscorlib"))
            {
                toVisit.AddToBack(module.Types.First(t => t.FullName == "System.Object"));
            }

            var inOrderGenerators = new List <TypeSdkGenerator>();

            while (toVisit.Count > 0)
            {
                var currentVisited = toVisit.RemoveFromBack();
                if (visitedTypes.Contains(currentVisited))
                {
                    continue;
                }

                var canVisit = true;
                void CheckDep(TypeSig ts)
                {
                    if (ts != null && ts.IsValueType && !ts.IsPrimitive)
                    {
                        //Console.WriteLine(ts.FullName + " is non primitive and is struct?");
                        foreach (var t2 in ts.UsedTypes())
                        {
                            var tn = t2.GetNonNestedTypeRefScope().ResolveTypeDef();
                            if (tn != null && tn != currentVisited && tn.DefinitionAssembly == module.Assembly && !visitedTypes.Contains(tn))
                            {
                                canVisit = false;
                                toVisit.AddToBack(tn);
                            }
                        }
                    }
                }

                var baseType = currentVisited.BaseType?.ResolveTypeDef();
                if (baseType != null && baseType.DefinitionAssembly == module.Assembly && !visitedTypes.Contains(baseType))
                {
                    canVisit = false;
                    toVisit.AddToBack(baseType);
                }

                foreach (var valueField in currentVisited.Fields)
                {
                    CheckDep(valueField.FieldType);
                }

                foreach (var method in currentVisited.Methods)
                {
                    foreach (var arg in method.Parameters)
                    {
                        CheckDep(arg.Type);
                    }

                    if (method.HasGenericParameters)
                    {
                        CheckDep(method.ReturnType);
                    }
                }

                if (!canVisit)
                {
                    toVisit.AddToFront(currentVisited);
                    continue;
                }

                visitedTypes.Add(currentVisited);
                inOrderGenerators.Add(new TypeSdkGenerator(currentVisited, currentVisited.ParsedFullNamespace()));
            }

            var dependencies = new HashSet <IAssembly>();

            void AddDependency(IAssembly assemblyRef)
            {
                if (assemblyRef == module.Assembly)
                {
                    return;
                }

                if (assemblyRef.Name.Contains("System.Private.CoreLib"))
                {
                    return;
                }

                dependencies.Add(assemblyRef);
            }

            void AddTypeDependency(ITypeDefOrRef typeDefOrRef)
            {
                if (typeDefOrRef == null)
                {
                    return;
                }

                if (typeDefOrRef.IsValueType && !typeDefOrRef.ResolveTypeDefThrow().IsEnum)
                {
                    AddDependency(typeDefOrRef.DefinitionAssembly);
                }
            }

            AddDependency(corlib);
            foreach (var dep in module.GetTypes().Where(t => !t.IsInterface))
            {
                if (dep.BaseType != null && !dep.IsEnum)
                {
                    AddDependency(dep.BaseType.DefinitionAssembly);
                }

                foreach (var field in dep.Fields)
                {
                    AddTypeDependency(field.FieldType.GetNonNestedTypeRefScope());
                }

                foreach (var method in dep.Methods)
                {
                    AddTypeDependency(method.ReturnType.GetNonNestedTypeRefScope());
                    foreach (var param in method.Parameters)
                    {
                        AddTypeDependency(param.Type.GetNonNestedTypeRefScope());
                    }
                }
            }

            var deps       = new HashSet <string>();
            var depBuilder = new StringBuilder();

            foreach (var d in dependencies)
            {
                var dn = d.Name.String.Parseable();
                if (deps.Add(dn))
                {
                    depBuilder.AppendLine($"#include \"..\\{dn}\\{dn}.hpp\"");
                }
            }

            var hdr     = new IndentedBuilder();
            var forward = new IndentedBuilder();
            var file    = new IndentedBuilder();

            foreach (var generator in inOrderGenerators)
            {
                forward.AppendIndented("namespace ");
                forward.Append(generator.Namespace);
                forward.AppendNewLine();

                forward.AppendIndentedLine("{");
                forward.Indent();

                generator.GenerateForwardTypeDefinition(forward);

                forward.Outdent();
                forward.AppendIndentedLine("}");

                if (!generator.TypeDef.IsInterface)
                {
                    hdr.AppendIndented("namespace ");
                    hdr.Append(generator.Namespace);
                    hdr.AppendNewLine();

                    hdr.AppendIndentedLine("{");
                    hdr.Indent();

                    generator.GenerateHeaderTypeDefinition(hdr);

                    hdr.Outdent();
                    hdr.AppendIndentedLine("}");
                }

                generator.GenerateImplementation(file);
            }

            var name = module.Assembly.Name.String.Parseable();
            var path = $"out/DLL2SDK/{name}";

            Directory.CreateDirectory(path);
            File.WriteAllText($"{path}/{name}.hpp", $@"//generated with dll2sdk
#pragma once
#include ""..\dll2sdk_forward.g.hpp""
{depBuilder}
{hdr}");
            File.WriteAllText($"{path}/{name}_forward.hpp", $@"//generated with dll2sdk
#pragma once
#include ""..\dll2sdk_forward.g.hpp""
{forward}
");
            File.WriteAllText($"{path}/{name}.cpp", $@"//generated with dll2sdk
#include ""{name}.hpp""
{file}");
            File.AppendAllText("out/DLL2SDK/dll2sdk_forward.g.hpp", $@"#include ""{name}\{name}_forward.hpp""
");
        }
Example #4
0
        public void GenerateHeaderTypeDefinition(IndentedBuilder builder)
        {
            builder.AppendIndented(TypeDef.TypeDefinitionStr());
            if (TypeDef.IsEnum)
            {
                string tss = TypeDef.GetEnumUnderlyingType().ParsedTypeSignatureStr();
                builder.Append(" : ");
                builder.AppendLine(tss);
                builder.AppendIndentedLine("{");
                builder.Indent();
                for (int index = 0; index < TypeDef.Fields.Count; index++)
                {
                    FieldDef field = TypeDef.Fields[index];
                    if (!field.IsSpecialName)
                    {
                        builder.AppendIndented($"{field.Name.String.Parseable()}_");
                        if (field.HasConstant)
                        {
                            builder.Append(" = ");
                            builder.Append($"static_cast<{tss}>(0x{field.Constant.Value:X})");
                        }
                        if (index < TypeDef.Fields.Count - 1)
                        {
                            builder.AppendLine(",");
                        }
                    }
                }
                builder.AppendNewLine();
            }
            else
            {
                if (!TypeDef.IsValueType && !TypeDef.IsInterface)
                {
                    builder.Append(" : ");
                    builder.Append(TypeDef.BaseType?.ToTypeSig().ParsedTypeSignatureStr() ?? "DLL2SDK::Object");
                }
                builder.AppendNewLine();
                builder.AppendIndentedLine("{");
                builder.Indent();
                if (TypeDef.HasNestedTypes)
                {
                    foreach (TypeDef type in TypeDef.NestedTypes)
                    {
                        new TypeSdkGenerator(type, Namespace).GenerateHeaderTypeDefinition(builder);
                    }
                }
                if (TypeDef.IsExplicitLayout)
                {
                    builder.AppendIndentedLine("union");
                    builder.AppendIndentedLine("{");
                    builder.Indent();
                    int i = 0;
                    foreach (FieldDef field in TypeDef.Fields)
                    {
                        if (!field.IsStatic)
                        {
                            builder.AppendIndentedLine("struct");
                            builder.AppendIndentedLine("{");
                            builder.Indent();
                            //so in other news c++ sucks
                            object offset = new System.ComponentModel.Int32Converter().ConvertFromString(field
                                                                                                         .CustomAttributes
                                                                                                         .First(a => a.TypeFullName.Contains("FieldOffset"))
                                                                                                         .GetNamedArgument("Offset", true).Value.ToString());
                            if (offset != null && (int)offset != 0)
                            {
                                builder.AppendIndentedLine($"uint8_t offset_{++i}[0x{offset:X}];");
                            }
                            builder.AppendIndentedLine(field.ParsedTypeDefinitionStr());

                            builder.Outdent();
                            builder.AppendIndentedLine("};");
                        }
                    }
                    builder.Outdent();
                    builder.AppendIndentedLine("};");
                }
                else
                {
                    foreach (FieldDef field in TypeDef.Fields)
                    {
                        if (!field.IsStatic)
                        {
                            builder.AppendIndentedLine(field.ParsedTypeDefinitionStr());
                        }
                    }
                }
                FieldDef[] staticFields = TypeDef.Fields.Where(f => f.IsStatic).ToArray();
                if (staticFields.Length > 0)
                {
                    if (TypeDef.IsValueType)
                    {
                        builder.AppendIndentedLine("/* NOTE: structure has static fields; this is not yet supported.");
                    }
                    builder.AppendIndentedLine("struct StaticFields");
                    builder.AppendIndentedLine("{");
                    builder.Indent();
                    foreach (FieldDef field in staticFields)
                    {
                        builder.AppendIndentedLine(field.ParsedTypeDefinitionStr());
                    }
                    builder.Outdent();
                    builder.AppendIndentedLine("};");
                    builder.AppendIndentedLine("StaticFields* GetStaticFields() { return reinterpret_cast<StaticFields*>(this->ClassPtr->StaticFieldsPtr); }");
                    if (TypeDef.IsValueType)
                    {
                        builder.AppendIndentedLine("*/");
                    }
                }
            }
            if (TypeDef.HasMethods)
            {
                MethodDef[] instancedMethods = TypeDef.Methods.Where(m => (!m.IsVirtual || !m.IsInterfacedMethod()) && !m.IsStatic).ToArray();
                MethodDef[] staticMethods    = TypeDef.Methods.Where(m => m.IsStatic && m.Name != "op_Explicit" && m.Name != "op_Implicit").ToArray();
                foreach (MethodDef instancedMethod in instancedMethods)
                {
                    builder.AppendIndentedLine(instancedMethod.DeclarationStr());
                }
                foreach (MethodDef staticMethod in staticMethods)
                {
                    builder.AppendIndentedLine(staticMethod.DeclarationStr());
                }
            }
            builder.Outdent();
            builder.AppendIndentedLine("};");
        }