diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index b1d6f2ff..ccbb0b3e 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -177,6 +177,7 @@ namespace Cxxi GeneratorKind = LanguageGeneratorKind.CSharp; GenerateLibraryNamespace = true; GenerateFunctionTemplates = false; + WriteOnlyWhenChanged = false; } public bool Verbose = false; @@ -200,5 +201,6 @@ namespace Cxxi public string IncludePrefix; public string WrapperSuffix; public LanguageGeneratorKind GeneratorKind; + public bool WriteOnlyWhenChanged; } } \ No newline at end of file diff --git a/src/Generator/Generators/CLI/CLIGenerator.cs b/src/Generator/Generators/CLI/CLIGenerator.cs index 357c62b6..147a91c7 100644 --- a/src/Generator/Generators/CLI/CLIGenerator.cs +++ b/src/Generator/Generators/CLI/CLIGenerator.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using Cxxi.Passes; using Cxxi.Types; namespace Cxxi.Generators.CLI @@ -8,11 +7,13 @@ namespace Cxxi.Generators.CLI public class CLIGenerator : Generator { private readonly ITypePrinter typePrinter; + private readonly FileHashes fileHashes; public CLIGenerator(Driver driver) : base(driver) { typePrinter = new CLITypePrinter(driver); Type.TypePrinter = typePrinter; + fileHashes = FileHashes.Load("hashes.ser"); } void WriteTemplate(TextTemplate template) @@ -22,11 +23,22 @@ namespace Cxxi.Generators.CLI + template.FileExtension; var path = Path.Combine(Driver.Options.OutputDir, file); + var fullPath = Path.GetFullPath(path); template.Generate(); Console.WriteLine(" Generated '" + file + "'."); - File.WriteAllText(Path.GetFullPath(path), template.ToString()); + + var str = template.ToString(); + + if(Driver.Options.WriteOnlyWhenChanged) + { + var updated = fileHashes.UpdateHash(path, str.GetHashCode()); + if(File.Exists(fullPath) && !updated) + return; + } + + File.WriteAllText(fullPath,str); } public override bool Generate(TranslationUnit unit) diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 6009ea87..c22c9a53 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -568,6 +568,9 @@ namespace Cxxi.Generators.CLI foreach (var field in @class.Fields) { + if(field.Ignore) + continue; + MarshalValueClassField(field, marshalVar); } } diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index 948c6204..35e3a2fa 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -251,9 +251,6 @@ namespace Cxxi.Generators.CLI WriteLine("{0} = {1};", variable, marshal.Context.Return); - if (!string.IsNullOrWhiteSpace(marshal.Context.SupportAfter)) - Write(marshal.Context.SupportAfter); - WriteCloseBraceIndent(); NewLine(); } @@ -269,6 +266,7 @@ namespace Cxxi.Generators.CLI var ctx = new MarshalContext(Driver) { + ArgName = field.Name, ReturnVarName = variable, ReturnType = field.Type }; @@ -276,6 +274,9 @@ namespace Cxxi.Generators.CLI var marshal = new CLIMarshalNativeToManagedPrinter(ctx); field.Visit(marshal); + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + Write(marshal.Context.SupportBefore); + WriteLine("return {0};", marshal.Context.Return); WriteCloseBraceIndent(); @@ -460,6 +461,7 @@ namespace Cxxi.Generators.CLI var ctx = new MarshalContext(Driver) { + ArgName = field.Name, ReturnVarName = nativeField, ReturnType = field.Type }; @@ -471,9 +473,6 @@ namespace Cxxi.Generators.CLI Write(marshal.Context.SupportBefore); WriteLine("{0} = {1};", field.Name, marshal.Context.Return); - - if (!string.IsNullOrWhiteSpace(marshal.Context.SupportAfter)) - Write(marshal.Context.SupportAfter); } } @@ -671,10 +670,9 @@ namespace Cxxi.Generators.CLI if (needsReturn) { - Write("return "); - var ctx = new MarshalContext(Driver) { + ArgName = "ret", ReturnVarName = "ret", ReturnType = retType }; @@ -682,7 +680,10 @@ namespace Cxxi.Generators.CLI var marshal = new CLIMarshalNativeToManagedPrinter(ctx); function.ReturnType.Visit(marshal); - WriteLine("{0};", marshal.Context.Return); + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + Write(marshal.Context.SupportBefore); + + WriteLine("return {0};", marshal.Context.Return); } } @@ -747,9 +748,6 @@ namespace Cxxi.Generators.CLI WriteLine("auto {0}{1} = {2};", marshal.VarPrefix, argName, marshal.Context.Return); - if (!string.IsNullOrWhiteSpace(marshal.Context.SupportAfter)) - Write(marshal.Context.SupportAfter); - var argText = marshal.ArgumentPrefix + argName; return new ParamMarshal {Name = argText, Param = param}; } diff --git a/src/Generator/Types/CppTypePrinter.cs b/src/Generator/Types/CppTypePrinter.cs index f31ebf21..a7adc3ac 100644 --- a/src/Generator/Types/CppTypePrinter.cs +++ b/src/Generator/Types/CppTypePrinter.cs @@ -93,12 +93,7 @@ namespace Cxxi.Types public string VisitTypedefType(TypedefType typedef, TypeQualifiers quals) { - var decl = typedef.Declaration; - - if (decl.Type == null) - return string.Empty; - - return decl.Type.Visit(this); + return "::" + typedef.Declaration.QualifiedOriginalName; } public string VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals) diff --git a/src/Generator/Types/Std/Stdlib.cs b/src/Generator/Types/Std/Stdlib.cs index 168a3fb5..e449646f 100644 --- a/src/Generator/Types/Std/Stdlib.cs +++ b/src/Generator/Types/Std/Stdlib.cs @@ -69,8 +69,6 @@ namespace Cxxi.Types.Std [TypeMap("std::vector")] public class Vector : TypeMap { - public override bool IsIgnored { get { return true; } } - public override string CLISignature(TypePrinterContext ctx) { return string.Format("System::Collections::Generic::List<{0}>^", @@ -79,12 +77,80 @@ namespace Cxxi.Types.Std public override void CLIMarshalToNative(MarshalContext ctx) { - throw new System.NotImplementedException(); + var templateType = Type as TemplateSpecializationType; + var type = templateType.Arguments[0].Type; + + var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name : ctx.ArgName; + + var tmpVarName = "_tmp" + entryString; + + var cppTypePrinter = new CppTypePrinter(ctx.Driver.TypeDatabase); + var nativeType = type.Type.Visit(cppTypePrinter); + + ctx.SupportBefore.WriteLine("auto {0} = std::vector<{1}>();", + tmpVarName, nativeType); + ctx.SupportBefore.WriteLine("for each({0} _element in {1})", + type.ToString(), entryString); + ctx.SupportBefore.WriteStartBraceIndent(); + { + var param = new Parameter + { + Name = "_element", + QualifiedType = type + }; + + var elementCtx = new MarshalContext(ctx.Driver) + { + Parameter = param, + ArgName = param.Name, + }; + + var marshal = new CLIMarshalManagedToNativePrinter(elementCtx); + type.Type.Visit(marshal); + + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + ctx.SupportBefore.Write(marshal.Context.SupportBefore); + + ctx.SupportBefore.WriteLine("auto _marshalElement = {0};", + marshal.Context.Return); + + ctx.SupportBefore.WriteLine("{0}.push_back(_marshalElement);",tmpVarName); + } + + ctx.SupportBefore.WriteCloseBraceIndent(); + + ctx.Return.Write(tmpVarName); } public override void CLIMarshalToManaged(MarshalContext ctx) { - throw new System.NotImplementedException(); + var templateType = Type as TemplateSpecializationType; + var type = templateType.Arguments[0].Type; + var tmpVarName = "_tmp" + ctx.ArgName; + + ctx.SupportBefore.WriteLine("auto {0} = gcnew System::Collections::Generic::List<{1}>();", tmpVarName, type.ToString()); + ctx.SupportBefore.WriteLine("for(auto _element : {0})",ctx.ReturnVarName); + ctx.SupportBefore.WriteStartBraceIndent(); + { + var elementCtx = new MarshalContext(ctx.Driver) + { + ReturnVarName = "_element", + ReturnType = type.Type + }; + + var marshal = new CLIMarshalNativeToManagedPrinter(elementCtx); + type.Type.Visit(marshal); + + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + ctx.SupportBefore.Write(marshal.Context.SupportBefore); + + ctx.SupportBefore.WriteLine("auto _marshalElement = {0};", marshal.Context.Return); + + ctx.SupportBefore.WriteLine("{0}->Add(_marshalElement);", tmpVarName); + } + ctx.SupportBefore.WriteCloseBraceIndent(); + + ctx.Return.Write(tmpVarName); } } diff --git a/src/Generator/Types/TypeMap.cs b/src/Generator/Types/TypeMap.cs index 55166cf1..c475774f 100644 --- a/src/Generator/Types/TypeMap.cs +++ b/src/Generator/Types/TypeMap.cs @@ -11,7 +11,6 @@ namespace Cxxi.Types { Driver = driver; SupportBefore = new TextGenerator(); - SupportAfter = new TextGenerator(); Return = new TextGenerator(); } @@ -21,7 +20,6 @@ namespace Cxxi.Types public CLIMarshalManagedToNativePrinter MarshalToNative; public TextGenerator SupportBefore { get; private set; } - public TextGenerator SupportAfter { get; private set; } public TextGenerator Return { get; private set; } public string ReturnVarName { get; set; } diff --git a/src/Generator/Utils/FileHashes.cs b/src/Generator/Utils/FileHashes.cs new file mode 100644 index 00000000..187d7dcd --- /dev/null +++ b/src/Generator/Utils/FileHashes.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; + +[Serializable] +class FileHashes +{ + private string serializedFile; + private Dictionary fileHashes = new Dictionary(); + + public bool UpdateHash(string file, int hash) + { + if(!fileHashes.ContainsKey(file)) + { + fileHashes.Add(file, hash); + Save(this, serializedFile); + return true; + } + + var oldHash = fileHashes[file]; + fileHashes[file] = hash; + Save(this, serializedFile); + + return oldHash != hash; + } + + public static FileHashes Load(string file) + { + var stream = File.Open(file, FileMode.OpenOrCreate); + var bformatter = new BinaryFormatter(); + + FileHashes obj; + if(stream.Length>0) + obj = (FileHashes)bformatter.Deserialize(stream); + else + obj = new FileHashes(); + obj.serializedFile = file; + stream.Close(); + + return obj; + } + + public static void Save(FileHashes obj, string file) + { + Stream stream = File.Open(file, FileMode.Create); + BinaryFormatter bformatter = new BinaryFormatter(); + + bformatter.Serialize(stream, obj); + stream.Close(); + } +} \ No newline at end of file