void AddForwardReference(List <ManagedClass> forwardRefs, TypeRefDefinition type, HeaderDefinition header) { if (type.IsBasic) { return; } switch (type.Kind) { case TypeKind.Pointer: case TypeKind.LValueReference: AddForwardReference(forwardRefs, type.Referenced, header); return; } var target = type.Target; if (target == null) { return; } if (target.IsExcluded || target.MarshalAsStruct || target.Header == header) { return; } var targetManaged = DotNetParser.GetManaged(target); if (!forwardRefs.Contains(targetManaged)) { forwardRefs.Add(targetManaged); } }
// If the type is defined in a conditionally compiled header, return the condition string. private string GetTypeConditional(TypeRefDefinition type) { var target = type.Target; if (target == null && type.Referenced != null) { target = type.Referenced.Target; } if (target == null) { return(null); } string headerConditional; string targetHeaderName = DotNetParser.GetManaged(target.Header).Name; if (headerConditionals.TryGetValue(targetHeaderName, out headerConditional)) { return(headerConditional); } return(null); }
void WriteMethodDefinition(ManagedMethod method, int numParameters, int overloadIndex, int level, ManagedParameter outValueParameter) { var nativeMethod = method.Native; if (nativeMethod.IsConstructor) { if (method.Parent.BaseClass == null) { Write("_native = "); } Write($"{GetFullNameC(method.Parent.Native)}_new"); } else { if (!nativeMethod.IsVoid) { if (outValueParameter != null) { // Temporary variable WriteLine(string.Format("{0} {1};", DotNetParser.GetManaged(outValueParameter.Native.Type.Referenced.Target).Name, outValueParameter.Name)); WriteTabs(level + 2); } else { Write($"return {BulletParser.GetTypeMarshalConstructorStartCS(nativeMethod)}"); } } Write($"{GetFullNameC(method.Parent.Native)}_{method.Native.Name}"); } if (overloadIndex != 0) { Write((overloadIndex + 1).ToString()); } Write('('); var parameters = method.Parameters.Take(numParameters) .Select(p => GetParameterMarshal(p)); if (outValueParameter != null) { parameters = parameters.Concat(new[] { $"out {outValueParameter.Name }" }); } // The first parameter is the instance pointer (if not constructor or static method) if (!nativeMethod.IsConstructor && !nativeMethod.IsStatic) { parameters = new[] { "_native" }.Concat(parameters); } Write(ListToLines(parameters, WriteTo.CS, level + 2)); if (nativeMethod.IsConstructor && method.Parent.BaseClass != null) { Write(")"); if (method.Parent.BaseClass.Native.HasPreventDelete) { Write(", false"); } WriteLine(")"); WriteLine(level + 1, "{"); } else { if (!nativeMethod.IsConstructor && !nativeMethod.IsVoid) { Write(BulletParser.GetTypeMarshalConstructorEndCS(nativeMethod)); } WriteLine(");"); } // Cache property values if (nativeMethod.IsConstructor) { var methodParent = method.Parent; while (methodParent != null) { foreach (var cachedProperty in methodParent.CachedProperties.OrderBy(p => p.Key)) { foreach (var param in method.Parameters) { if (param.Name.ToLower().Equals(cachedProperty.Key.ToLower()) && GetName(param.Native.Type).Equals(GetName(cachedProperty.Value.Property.Type))) { WriteLine(level + 2, $"{cachedProperty.Value.CacheFieldName} = {param.Name};"); } } } methodParent = methodParent.BaseClass; } } // Return temporary variable if (outValueParameter != null) { WriteLine(level + 2, $"return {outValueParameter.Name};"); } }
public override void Output() { var headers = DotNetParser.Headers.Values; if (headers.Count != 0) { Directory.CreateDirectory(Project.CppCliProjectPathFull); } foreach (var header in headers) { string headerFilename = Path.Combine(Project.CppCliProjectPathFull, header.Name + ".h"); OpenFile(headerFilename, WriteTo.Header); WriteLine("#pragma once"); WriteLine(); // Write includes if (header.Native.Includes.Count != 0) { foreach (var include in header.Native.Includes) { string includeName = DotNetParser.GetManaged(include).Name; WriteLine($"#include \"{includeName}.h\""); } WriteLine(); } // Write namespace WriteLine($"namespace {Project.NamespaceName}"); WriteLine("{"); hasHeaderWhiteSpace = true; // Find forward references var forwardRefs = new List <ManagedClass>(); foreach (var c in header.Classes) { FindForwardReferences(forwardRefs, c); } // Remove redundant forward references (header file already included) forwardRefs.RemoveAll(fr => header.Native.Includes.Contains(fr.Header.Native)); forwardRefs.Sort((r1, r2) => r1.Name.CompareTo(r2.Name)); // Write forward references var forwardRefHeaders = new List <ManagedHeader>(); foreach (ManagedClass c in forwardRefs) { WriteLine(1, $"ref class {c.Name};"); if (!forwardRefHeaders.Contains(c.Header)) { forwardRefHeaders.Add(c.Header); } hasHeaderWhiteSpace = false; } forwardRefHeaders.Add(header); forwardRefHeaders.Sort((r1, r2) => r1.Name.CompareTo(r2.Name)); string sourceFilename = Path.Combine(Project.CppCliProjectPathFull, header.Name + ".cpp"); OpenFile(sourceFilename, WriteTo.Source); WriteLine("#include \"StdAfx.h\""); WriteLine(); string headerConditional; if (headerConditionals.TryGetValue(header.Name, out headerConditional)) { WriteLine($"#ifndef {headerConditional}"); WriteLine(); } // Write statements to include forward referenced types if (forwardRefHeaders.Count != 0) { foreach (var refHeader in forwardRefHeaders) { bool hasHeaderConditional = false; if (headerConditionals.ContainsKey(refHeader.Name)) { hasHeaderConditional = true; if (headerConditionals.ContainsKey(header.Name) && headerConditionals[refHeader.Name] == headerConditionals[header.Name]) { hasHeaderConditional = false; } } if (hasHeaderConditional) { Write("#ifndef "); WriteLine(headerConditionals[refHeader.Name]); } WriteLine($"#include \"{refHeader.Name}.h\""); if (hasHeaderConditional) { WriteLine("#endif"); } } hasSourceWhiteSpace = false; } // Write classes var currentAccess = RefAccessSpecifier.Public; WriteClasses(header.Classes, ref currentAccess, 0); if (headerConditionals.ContainsKey(header.Name)) { WriteLine(); WriteLine("#endif"); } WriteLine("};", WriteTo.Header); CloseFile(WriteTo.Header); CloseFile(WriteTo.Source); } Console.WriteLine("Write complete"); }