diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 5a7dacfa..936141e9 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -133,6 +133,7 @@ namespace CppSharp TranslationUnitPasses.AddPass(new ResolveIncompleteDeclsPass()); TranslationUnitPasses.AddPass(new CleanInvalidDeclNamesPass()); TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass()); + TranslationUnitPasses.AddPass(new GenerateInlinesCodePass()); library.SetupPasses(this); @@ -260,6 +261,7 @@ namespace CppSharp public string OutputNamespace; public string OutputDir; public string LibraryName; + private string inlinesLibraryName; public bool OutputInteropIncludes; public bool GenerateLibraryNamespace; public bool GenerateFunctionTemplates; @@ -273,6 +275,19 @@ namespace CppSharp public int MaxIndent; public string CommentPrefix; + public string InlinesLibraryName + { + get + { + if (string.IsNullOrEmpty(inlinesLibraryName)) + { + return string.Format("{0}-inlines", OutputNamespace); + } + return inlinesLibraryName; + } + set { inlinesLibraryName = value; } + } + public bool IsCSharpGenerator { get { return GeneratorKind == LanguageGeneratorKind.CSharp; } diff --git a/src/Generator/Passes/CheckIgnoredDecls.cs b/src/Generator/Passes/CheckIgnoredDecls.cs index b715faba..fd888e26 100644 --- a/src/Generator/Passes/CheckIgnoredDecls.cs +++ b/src/Generator/Passes/CheckIgnoredDecls.cs @@ -86,6 +86,19 @@ namespace CppSharp.Passes function.Name, msg); return false; } + + if (param.Kind == ParameterKind.IndirectReturnType) + { + Class retClass; + param.Type.Desugar().IsTagDecl(out retClass); + if (retClass == null) + { + function.ExplicityIgnored = true; + Console.WriteLine("Function '{0}' was ignored due to an indirect return param not of a tag type", + function.Name); + return false; + } + } } return true; diff --git a/src/Generator/Passes/GenerateInlinesCodePass.cs b/src/Generator/Passes/GenerateInlinesCodePass.cs new file mode 100644 index 00000000..b194efa8 --- /dev/null +++ b/src/Generator/Passes/GenerateInlinesCodePass.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using CppSharp.AST; + +namespace CppSharp.Passes +{ + public class GenerateInlinesCodePass : TranslationUnitPass + { + private TranslationUnit currentUnit; + private readonly List headers = new List(); + private readonly List mangledInlines = new List(); + + public override bool VisitLibrary(Library library) + { + bool result = base.VisitLibrary(library); + var cppBuilder = new StringBuilder(); + headers.Sort(); + foreach (var header in headers) + cppBuilder.AppendFormat("#include \"{0}\"\n", header); + var cpp = string.Format("{0}.cpp", Driver.Options.InlinesLibraryName); + var path = Path.Combine(Driver.Options.OutputDir, cpp); + File.WriteAllText(path, cppBuilder.ToString()); + switch (Driver.Options.Abi) + { + case CppAbi.Microsoft: + var defBuilder = new StringBuilder("EXPORTS\r\n"); + for (int i = 0; i < mangledInlines.Count; i++) + defBuilder.AppendFormat(" {0} @{1}\r\n", + mangledInlines[i], i + 1); + File.WriteAllText(Path.ChangeExtension(path, "def"), + defBuilder.ToString()); + break; + default: + var symbolsBuilder = new StringBuilder(); + foreach (var mangledInline in mangledInlines) + symbolsBuilder.AppendFormat("{0}\n", mangledInline); + File.WriteAllText(Path.ChangeExtension(path, "txt"), + symbolsBuilder.ToString()); + break; + } + return result; + } + + public override bool VisitTranslationUnit(TranslationUnit unit) + { + currentUnit = unit; + return base.VisitTranslationUnit(unit); + } + + public override bool VisitFunctionDecl(Function function) + { + CheckForSymbols(function); + return base.VisitFunctionDecl(function); + } + + public override bool VisitVariableDecl(Variable variable) + { + CheckForSymbols(variable); + return base.VisitVariableDecl(variable); + } + + private void CheckForSymbols(IMangledDecl mangled) + { + string symbol = mangled.Mangled; + var declaration = (Declaration) mangled; + if (!declaration.Ignore && declaration.Access != AccessSpecifier.Private && + !Driver.LibrarySymbols.FindSymbol(ref symbol) && + !currentUnit.FilePath.EndsWith("_impl.h") && + !currentUnit.FilePath.EndsWith("_p.h")) + { + if (!headers.Contains(currentUnit.FileName)) + headers.Add(currentUnit.FileName); + if (!mangledInlines.Contains(mangled.Mangled)) + mangledInlines.Add(mangled.Mangled); + } + } + } +}