diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index be0f2a16..380dd58b 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -253,8 +253,12 @@ namespace CppSharp TranslationUnitPasses.AddPass(new ResolveIncompleteDeclsPass()); TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass()); - if (Options.IsCSharpGenerator && Options.GenerateInlines) - TranslationUnitPasses.AddPass(new GenerateInlinesCodePass()); + if (Options.IsCSharpGenerator) + { + if (Options.GenerateInlines) + TranslationUnitPasses.AddPass(new GenerateInlinesCodePass()); + TranslationUnitPasses.AddPass(new GenerateTemplatesCodePass()); + } library.SetupPasses(this); diff --git a/src/Generator/Options.cs b/src/Generator/Options.cs index b1293b2c..4b8a37ce 100644 --- a/src/Generator/Options.cs +++ b/src/Generator/Options.cs @@ -150,7 +150,6 @@ namespace CppSharp public Encoding Encoding { get; set; } - private string inlinesLibraryName; public string InlinesLibraryName { get @@ -164,6 +163,19 @@ namespace CppSharp set { inlinesLibraryName = value; } } + public string TemplatesLibraryName + { + get + { + if (string.IsNullOrEmpty(templatesLibraryName)) + { + return string.Format("{0}-templates", OutputNamespace); + } + return templatesLibraryName; + } + set { templatesLibraryName = value; } + } + public bool IsCSharpGenerator { get { return GeneratorKind == GeneratorKind.CSharp; } @@ -193,6 +205,9 @@ namespace CppSharp /// C# end only: force patching of the virtual entries of the functions in this list. /// public List ExplicitlyPatchedVirtualFunctions { get; private set; } + + private string inlinesLibraryName; + private string templatesLibraryName; } public class InvalidOptionException : Exception diff --git a/src/Generator/Passes/GenerateInlinesCodePass.cs b/src/Generator/Passes/GenerateInlinesCodePass.cs index 6b3513b2..da5dbe44 100644 --- a/src/Generator/Passes/GenerateInlinesCodePass.cs +++ b/src/Generator/Passes/GenerateInlinesCodePass.cs @@ -8,7 +8,6 @@ namespace CppSharp.Passes { public override bool VisitLibrary(ASTContext context) { - Directory.CreateDirectory(Driver.Options.OutputDir); WriteInlinesIncludes(); return true; } @@ -19,6 +18,7 @@ namespace CppSharp.Passes foreach (var header in Driver.Options.Headers) cppBuilder.AppendFormat("#include <{0}>\n", header); var cpp = string.Format("{0}.cpp", Driver.Options.InlinesLibraryName); + Directory.CreateDirectory(Driver.Options.OutputDir); var path = Path.Combine(Driver.Options.OutputDir, cpp); File.WriteAllText(path, cppBuilder.ToString()); } diff --git a/src/Generator/Passes/GenerateTemplatesCodePass.cs b/src/Generator/Passes/GenerateTemplatesCodePass.cs new file mode 100644 index 00000000..c1548526 --- /dev/null +++ b/src/Generator/Passes/GenerateTemplatesCodePass.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using CppSharp.AST; +using CppSharp.AST.Extensions; +using CppSharp.Types; + +namespace CppSharp.Passes +{ + public class GenerateTemplatesCodePass : TranslationUnitPass + { + public override bool VisitLibrary(ASTContext context) + { + base.VisitLibrary(context); + WriteTemplateInstantiations(); + return true; + } + + public override bool VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals) + { + if (AlreadyVisited(template) || template.Template.Access == AccessSpecifier.Private) + return false; + + if (template.Arguments.Select(a => a.Type.Type.Desugar()).All(t => t.IsAddress() && !t.GetFinalPointee().IsDependent)) + { + var cppTypePrinter = new CppTypePrinter { PrintScopeKind = CppTypePrintScopeKind.Qualified }; + templateInstantiations.Add(string.Format("{0}<{1}>", template.Template.Name, + string.Join(", ", template.Arguments.Select(a => a.Type.Type.Visit(cppTypePrinter))))); + } + + return true; + } + + private void WriteTemplateInstantiations() + { + var cppBuilder = new StringBuilder(); + foreach (var header in Driver.Options.Headers) + cppBuilder.AppendFormat("#include <{0}>\n", header); + foreach (var templateInstantiation in templateInstantiations) + cppBuilder.AppendFormat("\ntemplate class {0};", templateInstantiation); + var cpp = string.Format("{0}.cpp", Driver.Options.TemplatesLibraryName); + Directory.CreateDirectory(Driver.Options.OutputDir); + var path = Path.Combine(Driver.Options.OutputDir, cpp); + File.WriteAllText(path, cppBuilder.ToString()); + } + + private HashSet templateInstantiations = new HashSet(); + } +}