public void GenerateForwardTypeDefinition(IndentedBuilder builder) { builder.AppendIndented(TypeDef.TypeDefinitionStr()); if (TypeDef.IsEnum) { builder.Append(" : "); builder.Append(TypeDef.GetEnumUnderlyingType().ParsedTypeSignatureStr()); } builder.Append(";"); builder.AppendNewLine(); }
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); } } }
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"" "); }
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("};"); }