Example #1
0
        static void Main(string[] args)
        {
            var headerFile = Path.Combine(AppContext.BaseDirectory, "Headers", "renderdoc_app.h");
            var options    = new CppParserOptions
            {
                ParseMacros = true,
                Defines     =
                {
                    "_WIN32",
                }
            };

            var compilation = CppParser.ParseFile(headerFile, options);

            // Print diagnostic messages
            if (compilation.HasErrors)
            {
                foreach (var message in compilation.Diagnostics.Messages)
                {
                    Debug.WriteLine(message);
                }
            }
            else
            {
                string outputPath = "..\\..\\..\\..\\WaveEngine.Bindings.RenderDoc\\Generated";
                CsCodeGenerator.Instance.Generate(compilation, outputPath);
            }
        }
Example #2
0
        static void Main(string[] args)
        {
            var flavors = new string[] { "Dawn", "Browser" };

            foreach (var flavor in flavors)
            {
                var headerFile = Path.Combine(AppContext.BaseDirectory, "Headers", flavor, "webgpu.h");
                var options    = new CppParserOptions
                {
                    ParseMacros = true,
                    Defines     =
                    {
                        "WGPU_SHARED_LIBRARY",
                        "_WIN32",
                        "WGPU_SKIP_PROCS"
                    }
                };

                var compilation = CppParser.ParseFile(headerFile, options);

                // Print diagnostic messages
                if (compilation.HasErrors)
                {
                    foreach (var message in compilation.Diagnostics.Messages)
                    {
                        Debug.WriteLine(message);
                    }
                }
                else
                {
                    string basePath = "..\\..\\..\\..\\WaveEngine.Bindings.WebGPU";
                    CsCodeGenerator.Instance.Generate(compilation, basePath, flavor);
                }
            }
        }
Example #3
0
        private void ParseSkiaHeaders()
        {
            Log?.LogVerbose("Parsing skia headers...");

            var options = new CppParserOptions();

            foreach (var header in config.IncludeDirs)
            {
                var path = Path.Combine(SkiaRoot, header);
                options.IncludeFolders.Add(path);
            }

            var headers = new List <string>();

            foreach (var header in config.Headers)
            {
                var path = Path.Combine(SkiaRoot, header.Key);
                options.IncludeFolders.Add(path);
                foreach (var filter in header.Value)
                {
                    headers.AddRange(Directory.EnumerateFiles(path, filter));
                }
            }

            compilation = CppParser.ParseFiles(headers, options);

            if (compilation == null || compilation.HasErrors)
            {
                Log?.LogError("Parsing headers failed.");
                throw new Exception("Parsing headers failed.");
            }
        }
Example #4
0
        private static CppCompilation Compile(GenerateConfig config, string directory)
        {
            Environment.CurrentDirectory = directory;

            Regex[] sourcePatterns = config.CompileConfig.Sources
                                     .Select(StringExtension.MakeWildcardPattern)
                                     .ToArray();

            Regex[] sourceExcludePatterns = config.CompileConfig.SourceExcludes
                                            .Select(StringExtension.MakeWildcardPattern)
                                            .ToArray();

            List <string> sources = Directory.GetFiles(directory, "*.*", SearchOption.AllDirectories)
                                    .Select(f => Path.GetRelativePath(directory, f).Replace("\\", "/"))
                                    .Where(f =>
            {
                if (!sourcePatterns.Any(p => p.IsMatch(f)))
                {
                    return(false);
                }

                if (sourceExcludePatterns.Any(p => p.IsMatch(f)))
                {
                    return(false);
                }

                return(true);
            })
                                    .ToList();

            var parserOptions = new CppParserOptions
            {
                ParseAsCpp          = true,
                ParseMacros         = true,
                ParseAttributes     = true,
                ParseSystemIncludes = true,
                AdditionalArguments =
                {
                    "--target=x86_64-apple-darwin19.5.0",
                    "-Wall",
                    "-Wno-unused-function",
                    "-Wno-unused-value",
                    "-Wno-unused-variable",
                    "-fno-strict-aliasing",
                    "-fwrapv",
                    "-fPIC",
                    "-Wno-nullability-completeness"
                }
            };

            parserOptions.IncludeFolders.AddRange(GetGnuIncludes());
            parserOptions.IncludeFolders.Add("./");
            parserOptions.IncludeFolders.AddRange(config.CompileConfig.IncludeFolders);

            return(CppParser.ParseFiles(sources, parserOptions));
        }
Example #5
0
        private static CppCompilation Parse(string vlcDir)
        {
            var parserOptions = new CppParserOptions
            {
                ParseComments = NoComment
            };

            parserOptions.IncludeFolders.Add(Path.Combine(vlcDir, include));
            return(CppParser.ParseFile(BuildPath(vlcDir, vlch), parserOptions));
        }
Example #6
0
        public CppParserOptions ToParserOptions()
        {
            Validate();
            AddSystemIncludes();

            var opts = new CppParserOptions();

            opts.Defines.AddRange(Defines);
            opts.IncludeFolders.AddRange(ToAbsolutePaths(IncludeFolders));
            opts.SystemIncludeFolders.AddRange(SystemIncludeFolders);
            opts.AdditionalArguments.AddRange(AdditionalArguments);
            opts.AutoSquashTypedef = AutoSquashTypedef;
            opts.TargetSystem      = TargetSystem;
            opts.ParseComments     = ParseComments;

            return(opts);
        }
Example #7
0
        static CppCompilation Do(String file, ClConfig cfg)
        {
            var options = new CppParserOptions()
            {
                // Pass the defines -DMYDEFINE to the C++ parser
                Defines        = { },
                IncludeFolders = { },
                TargetCpu      = CppTargetCpu.X86_64,
            };

            options.ParseSystemIncludes = false;
            options.ParseComments       = false;
            options.AdditionalArguments.Add("-fno-complete-member-pointers");
            options.AdditionalArguments.Add("/TC");
            options.AdditionalArguments.Add("-std c99");
            options.AdditionalArguments.Add("/c");
            options.AdditionalArguments.Add("-fms-extensions");
            options.AdditionalArguments.Add("-fms-compatibility");
            options.AdditionalArguments.Add(" -fms-compatibility-version=19");
            options.ParseAsCpp = false;

            options.EnableFunctionBodies();

            foreach (KeyValuePair <string, string> kv in cfg.define)
            {
                String d = kv.Value == null ? (kv.Key) : (kv.Key + "=" + kv.Value);
                options.Defines.Add(d);
            }
            options.Defines.Add("CPP_AST_FIXED");

            foreach (String include in cfg.include)
            {
                options.IncludeFolders.Add(include);
            }

            options.ConfigureForWindowsMsvc();

            var compilation = CppParser.ParseFile(file, options);

            return(compilation);
        }
Example #8
0
        public void Process(string[] args)
        {
            var input_file = "test.cpp";

            var input_text = File.ReadAllText(input_file, encoding: Encoding.UTF8);

            var options = new CppParserOptions();
            //options.ParseAttributes = true;



            var compilation = CppParser.Parse(input_text, options);



            Context.Instance = new Context();

            foreach (var cpp_class in compilation.Classes)
            {
                HandleClass(cpp_class);
            }
        }
Example #9
0
        static void Main(string[] args)
        {
            var headerFile = Path.Combine(AppContext.BaseDirectory, "ImGUI", "cimgui.h");
            var options    = new CppParserOptions
            {
                ParseMacros = true,
                Defines     =
                {
                    "CIMGUI_DEFINE_ENUMS_AND_STRUCTS"
                }
            };

            var compilation = CppParser.ParseFile(headerFile, options);

            if (compilation.HasErrors)
            {
                foreach (var message in compilation.Diagnostics.Messages)
                {
                    Console.WriteLine(message);
                }
            }

            CsCodeGenerator.Generate(compilation, "../../../../src/SharpImGUI/Generated/");
        }
Example #10
0
        public static void Main(string[] args)
        {
            // In this sample we are going to bind a few C++ classes from https://github.com/lemire/simdjson
            // the library has "singleheader" file so we don't have to collect all needed files + includes
            // see https://github.com/lemire/simdjson/tree/master/singleheader


            string outputFolder = "../../../Output/";

            if (!Directory.Exists(outputFolder))
            {
                Directory.CreateDirectory(outputFolder);
            }

            Console.WriteLine("Downloading simdjson sources...");

            HttpClient httpClient           = new HttpClient();
            string     simdJsonSingleHeader = httpClient.GetStringAsync("https://raw.githubusercontent.com/lemire/simdjson/master/singleheader/simdjson.h").Result;

            File.WriteAllText(Path.Combine(outputFolder, @"simdjson.h"), simdJsonSingleHeader);

            Console.WriteLine("Downloaded! Parsing...");

            var options = new CppParserOptions();

            // TODO: test on macOS
            options.ConfigureForWindowsMsvc(CppTargetCpu.X86_64);
            options.AdditionalArguments.Add("-std=c++17");
            CppCompilation compilation = CppParser.ParseFile(Path.Combine(outputFolder, @"simdjson.h"), options);

            if (compilation.DumpErrorsIfAny())
            {
                Console.ReadKey();
                return;
            }

            var mapper = new TypeMapper(compilation);

            // Register native types we don't want to bind (or any method with them in parameters)
            mapper.RegisterUnsupportedTypes(
                "simdjson",          // it's empty - we don't need it
                "basic_string",      // TODO:
                "basic_string_view", // TODO
                "basic_ostream");    // TODO:

            var templateManager = new TemplateManager();

            // Add additional stuff we want to see in the bindings.c
            templateManager
            .AddToCHeader(@"#include ""simdjson.h""")
            .SetGlobalFunctionsClassName("GlobalFunctions");

            PinvokeGenerator.Generate(mapper,
                                      templateManager,
                                      @namespace: "MyNamespace",
                                      dllImportPath: @"""simdjson.dll""",
                                      outCFile:  Path.Combine(outputFolder, "Bindings.c"),
                                      outCsFile: Path.Combine(outputFolder, "Bindings.cs"));

            Console.WriteLine("Done. See Output folder.");
        }
Example #11
0
 private CppParserOptions(CppParserOptions.__Internal native, bool skipVTables = false)
     : this(__CopyValue(native), skipVTables)
 {
     __ownsNativeInstance = true;
     NativeToManagedMap[__Instance] = this;
 }
Example #12
0
 private static void* __CopyValue(CppParserOptions.__Internal native)
 {
     var ret = Marshal.AllocHGlobal(156);
     global::CppSharp.Parser.CppParserOptions.__Internal.cctor_2(ret, new global::System.IntPtr(&native));
     return ret.ToPointer();
 }
Example #13
0
 public static CppParserOptions __CreateInstance(CppParserOptions.__Internal native, bool skipVTables = false)
 {
     return new CppParserOptions(native, skipVTables);
 }
Example #14
0
        private static void GenerateFromCHeaders(string basePath, string outDirPath, bool onlyStdCall)
        {
            var options = new CppParserOptions();
            var files   = new List <string>(Directory.GetFiles(Path.Combine(basePath, "include", "capi"), "*.h"));

            files.Add(Path.Combine(basePath, "include", "cef_version.h"));
            files.Add(Path.Combine(basePath, "include", "cef_api_hash.h"));
            options.IncludeFolders.Add(ApplyHotPatch(basePath));
            options.IncludeFolders.Add(basePath);

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                options.IncludeFolders.Add("/usr/include/clang/8/include");
                options.TargetAbi    = "gnu";
                options.TargetCpu    = CppTargetCpu.X86_64;
                options.TargetSystem = "linux";
                options.TargetVendor = "pc";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                options.Defines.Add("_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH");
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                //options.TargetCpu = CppTargetCpu.X86_64;
                options.TargetSystem = "darwin";
                options.TargetVendor = "apple";
                options.SystemIncludeFolders.Add("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include");
                options.SystemIncludeFolders.Add("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1");
                options.SystemIncludeFolders.Add("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include");
                options.SystemIncludeFolders.Add("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0/include");
                options.AdditionalArguments.Add("-stdlib=libc++");
            }

            var nativeBuild = new NativeCefApiBuilder(onlyStdCall)
            {
                Namespace     = "CefNet.CApi",
                BaseDirectory = basePath
            };

            var enumBuild = new NativeCefApiBuilder(onlyStdCall)
            {
                Namespace     = "CefNet",
                BaseDirectory = basePath
            };

            CppCompilation compilation = CppParser.ParseFiles(files, options);

            if (compilation.HasErrors)
            {
                foreach (var msg in compilation.Diagnostics.Messages)
                {
                    Console.WriteLine(msg);
                }

                Environment.Exit(-1);
                return;
            }
            var aliasResolver = new AliasResolver(compilation);

            nativeBuild.ResolveCefTypeDef += aliasResolver.HandleResolveEvent;
            enumBuild.ResolveCefTypeDef   += aliasResolver.HandleResolveEvent;
            Func <string, string> resolveType = aliasResolver.ResolveNonFail;

            foreach (CppClass @class in compilation.Classes)
            {
                string source = @class.Span.Start.File;
                if (!source.Contains("capi") && !source.Contains("internal"))
                {
                    continue;
                }

                if (IgnoreClasses.Contains(@class.Name))
                {
                    continue;
                }

                string fileName = aliasResolver.ResolveNonFail(@class.Name);
                using (var csfile = new StreamWriter(Path.Combine(outDirPath, "Native", "Types", fileName + ".cs"), false, Encoding.UTF8))
                    using (var ilfile = new StreamWriter(Path.Combine(outDirPath, "Native", "MSIL", fileName + ".il"), false, Encoding.UTF8))
                    {
                        nativeBuild.Format(@class, csfile, ilfile);
                        csfile.Flush();
                        ilfile.Flush();
                    }
            }

            foreach (CppTypedef typedef in compilation.Typedefs)
            {
                string name = typedef.Name;
                if (name.StartsWith("cef_string_") ||
                    name == "cef_color_t"
                    //|| name == "cef_platform_thread_id_t"
                    || name == "cef_platform_thread_handle_t")
                {
                    var sb = new StringBuilder();
                    try
                    {
                        var w = new StringWriter(sb);
                        nativeBuild.Format(typedef, w);
                        w.Flush();
                        w.Dispose();
                    }
                    catch (InvalidOperationException)
                    {
                        continue;
                    }
                    string fileName = aliasResolver.ResolveNonFail(typedef.Name);
                    File.WriteAllText(Path.Combine(outDirPath, "Native", "Typedefs", fileName + ".cs"), sb.ToString(), Encoding.UTF8);
                }
            }

            foreach (CppEnum @enum in compilation.Enums)
            {
                string fileName = aliasResolver.ResolveNonFail(@enum.Name);
                using (var csfile = new StreamWriter(Path.Combine(outDirPath, "Managed", "Enums", fileName + ".cs"), false, Encoding.UTF8))
                {
                    enumBuild.Format(@enum, csfile);
                    csfile.Flush();
                }
            }


            var api = new CefApiClass("CefNativeApi")
            {
                Functions = compilation.Functions,
                ApiHash   = GetApiHash(basePath)
            };

            using (var csfile = new StreamWriter(Path.Combine(outDirPath, "Native", "CefNativeApi.cs"), false, Encoding.UTF8))
            {
                nativeBuild.Format(api, csfile);
                csfile.Flush();
            }
        }
Example #15
0
    public static int Main(string[] args)
    {
        string outputPath = AppContext.BaseDirectory;

        if (args.Length > 0)
        {
            outputPath = args[0];
        }

        if (!Path.IsPathRooted(outputPath))
        {
            outputPath = Path.Combine(AppContext.BaseDirectory, outputPath);
        }

        if (!Directory.Exists(outputPath))
        {
            Directory.CreateDirectory(outputPath);
        }

        string?headerFile = Path.Combine(AppContext.BaseDirectory, "vulkan", "vulkan.h");
        var    options    = new CppParserOptions
        {
            ParseMacros = true,
            Defines     =
            {
                "VK_USE_PLATFORM_ANDROID_KHR",
                "VK_USE_PLATFORM_IOS_MVK",
                "VK_USE_PLATFORM_MACOS_MVK",
                "VK_USE_PLATFORM_METAL_EXT",
                "VK_USE_PLATFORM_VI_NN",
                //"VK_USE_PLATFORM_WAYLAND_KHR",
                //"VK_USE_PLATFORM_WIN32_KHR",
                //"VK_USE_PLATFORM_SCREEN_QNX",
                "VK_ENABLE_BETA_EXTENSIONS"
            }
        };

        var compilation = CppParser.ParseFile(headerFile, options);

        // Print diagnostic messages
        if (compilation.HasErrors)
        {
            foreach (var message in compilation.Diagnostics.Messages)
            {
                if (message.Type == CppLogMessageType.Error)
                {
                    var currentColor = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(message);
                    Console.ForegroundColor = currentColor;
                }
            }

            return(0);
        }

        bool generateFuncFile = false;

        if (generateFuncFile)
        {
            File.Delete("Vk.txt");
            foreach (var func in compilation.Functions)
            {
                var signature    = new System.Text.StringBuilder();
                var argSignature = CsCodeGenerator.GetParameterSignature(func, true);
                signature
                .Append(func.ReturnType.GetDisplayName())
                .Append(" ")
                .Append(func.Name)
                .Append("(")
                .Append(argSignature)
                .Append(")");
                File.AppendAllText("Vk.txt", signature.ToString() + Environment.NewLine);
            }
        }

        CsCodeGenerator.Generate(compilation, outputPath);
        return(0);
    }
Example #16
0
        public static void Main(string[] args)
        {
            // input (single header)
            string headerPath = Path.Combine(Environment.CurrentDirectory, "../../src/BindingsForNativeLib/SimdJsonNative/simdjson.h");

            // output
            string cgluePath    = Path.Combine(Environment.CurrentDirectory, "../../src/BindingsForNativeLib/SimdJsonNative/bindings.cpp");
            string bindingsPath = Path.Combine(Environment.CurrentDirectory, "../../src/BindingsForNativeLib/SimdJsonSharp.Bindings/Bindings.Generated.cs");

            var options = new CppParserOptions();

            // TODO: test on macOS
            options.ConfigureForWindowsMsvc(CppTargetCpu.X86_64);
            options.AdditionalArguments.Add("-std=c++17");
            CppCompilation compilation = CppParser.ParseFile(headerPath, options);

            if (compilation.DumpErrorsIfAny())
            {
                Console.ReadKey();
                return;
            }

            var mapper = new TypeMapper(compilation);

            mapper.RenamingForApi += (nativeName, isMethod) =>
            {
                if (nativeName == "iterator")
                {
                    return("ParsedJsonIteratorN");
                }
                if (!isMethod)
                {
                    return(nativeName + "N"); // SimdJsonSharp has two C# APIs: 1) managed 2) bindings - postfixed with 'N'
                }
                if (nativeName == "get_type")
                {
                    return("GetTokenType");
                }
                if (nativeName == "get_string")
                {
                    return("GetUtf8String");
                }
                return(nativeName);
            };

            // init_state_machine requires external linkage (impl)
            mapper.RegisterUnsupportedMethod(null, "init_state_machine");

            // Register native types we don't want to bind (or any method with them in parameters)
            mapper.RegisterUnsupportedTypes(
                "simdjson", // it's empty - we don't need it
                "__m128i",
                "simd_input",
                "utf8_checking_state",
                "basic_string",      // TODO:
                "basic_string_view", // TODO
                "basic_ostream");    // TODO:

            var templateManager = new TemplateManager();

            // Add additional stuff we want to see in the bindings.c
            templateManager
            .AddToCHeader(@"#include ""simdjson.h""")
            .AddToCHeader(@"using namespace simdjson;")
            .SetGlobalFunctionsClassName("SimdJsonN");

            PinvokeGenerator.Generate(mapper,
                                      templateManager,
                                      @namespace: "SimdJsonSharp",
                                      dllImportPath: @"SimdJsonN.NativeLib",
                                      outCFile: cgluePath,
                                      outCsFile: bindingsPath);

            Console.WriteLine("Done.");
        }
Example #17
0
        public void ParseAssert(string text, Action <CppCompilation> assertCompilation, CppParserOptions options = null, bool asFile = true)
        {
            if (assertCompilation == null)
            {
                throw new ArgumentNullException(nameof(assertCompilation));
            }

            options = options ?? new CppParserOptions();
            var currentDirectory = Environment.CurrentDirectory;
            var headerFilename   = $"{TestContext.CurrentContext.Test.FullName}-{TestContext.CurrentContext.Test.ID}.h";
            var headerFile       = Path.Combine(currentDirectory, headerFilename);

            // Parse in memory
            var compilation = CppParser.Parse(text, options, headerFilename);

            foreach (var diagnosticsMessage in compilation.Diagnostics.Messages)
            {
                Console.WriteLine(diagnosticsMessage);
            }

            assertCompilation(compilation);

            if (asFile)
            {
                // Parse single file from disk
                File.WriteAllText(headerFile, text);
                compilation = CppParser.ParseFile(headerFile, options);
                assertCompilation(compilation);
            }
        }
Example #18
0
        public static DNA Create(
            List <string> include,
            List <string> exclude,
            bool includeByRef,
            List <string> headers,
            string dnaVersion,
            bool verbose
            )
        {
            var options = new CppParserOptions();
            // options.ParseAsCpp = false;

            var compilation = CppParser.ParseFiles(headers, options);

            foreach (var message in compilation.Diagnostics.Messages)
            {
                if (message.Type == CppLogMessageType.Error || verbose)
                {
                    Console.Error.WriteLine(message);
                }
            }

            var dna = new DNA
            {
                Version  = dnaVersion,
                Entities = new Dictionary <string, Entity>()
            };

            // TODO: Support enums somehow - e.g. CustomDataType that can change between DNA versions
            // https://github.com/sobotka/blender/blob/master/source/blender/makesdna/DNA_customdata_types.h#L90
            foreach (var cenum in compilation.Enums)
            {
                //Console.WriteLine(cenum);
            }

            // Print all structs with all fields
            foreach (var cstruct in compilation.Classes)
            {
                var name = cstruct.Name;

                // Skip non structs
                if (cstruct.ClassKind != CppClassKind.Struct)
                {
                    if (include != null && include.Contains(name))
                    {
                        throw new Exception(
                                  $"Required include [{name}] is not a supported type. Found [{cstruct.ClassKind}]."
                                  );
                    }
                    continue;
                }

                // If it's on the include list OR we don't have one and it's not in the exclusions, add.
                if ((include != null && include.Contains(name)) ||
                    (include == null && exclude != null && !exclude.Contains(name)) ||
                    (include == null && exclude == null)
                    )
                {
                    AddEntity(dna, cstruct, includeByRef);
                }
            }

            // Check - make sure all entities in the include list were found.
            if (include != null)
            {
                var missing = new List <string>();
                foreach (var name in include)
                {
                    if (!dna.Entities.ContainsKey(name))
                    {
                        missing.Add(name);
                    }
                }

                if (missing.Count > 0)
                {
                    throw new Exception("Could not load required names: " + string.Join(", ", missing));
                }
            }

            return(dna);
        }
Example #19
0
        private async Task <int> OnExecuteAsync(CommandLineApplication app,
                                                CancellationToken cancellationToken = default)
        {
            var outputDir = Path.IsPathFullyQualified(OutputProjectDir)
                ? OutputProjectDir
                : Path.GetFullPath(OutputProjectDir);

            Directory.CreateDirectory(outputDir);

            var workspace   = new AdhocWorkspace();
            var projectId   = ProjectId.CreateNewId();
            var projectInfo = ProjectInfo.Create(projectId, VersionStamp.Create(), "XP.SDK", "XP.SDK", LanguageNames.CSharp)
                              .WithDefaultNamespace("XP.SDK");
            var project = workspace.AddProject(projectInfo);

            var typeMap = new TypeMap(BuildTypeCallback);

            _enumBuilder = new EnumBuilder(workspace, projectId, outputDir, typeMap)
                           .Map("xpMainWindowStyle_MainWindow", "MainWindowType")
                           .Map("xpProperty_MainWindowType", "MainWindowProperty")
                           .Map("xpMessage_CloseButtonPushed", "MainWindowMessage")
                           .Map("xpSubWindowStyle_SubWindow", "SubWindowType")
                           .Map("xpProperty_SubWindowType", "SubWindowProperty")
                           .Map("xpPushButton", "ButtonType")
                           .Map("xpButtonBehaviorPushButton", "ButtonBehavior")
                           .Map("xpProperty_ButtonType", "ButtonProperty")
                           .Map("xpMsg_PushButtonPressed", "ButtonMessage")
                           .Map("xpTextEntryField", "TextFieldType")
                           .Map("xpProperty_EditFieldSelStart", "TextFieldProperty")
                           .Map("xpMsg_TextFieldChanged", "TextFieldMessage")
                           .Map("xpScrollBarTypeScrollBar", "ScrollBarType")
                           .Map("xpProperty_ScrollBarSliderPosition", "ScrollBarProperty")
                           .Map("xpMsg_ScrollBarSliderPositionChanged", "ScrollBarMessage")
                           .Map("xpProperty_CaptionLit", "CaptionProperty")
                           .Map("xpShip", "GeneralGraphicsType")
                           .Map("xpProperty_GeneralGraphicsType", "GeneralGraphicsProperty")
                           .Map("xpProperty_ProgressPosition", "ProgressBarProperty");
            _handleBuilder   = new HandleBuilder(workspace, projectId, outputDir, typeMap);
            _delegateBuilder = new DelegateBuilder(workspace, projectId, outputDir, typeMap);
            _structBuilder   = new StructBuilder(workspace, projectId, outputDir, typeMap);
            var functionBuilder = new FunctionBuilder(workspace, projectId, outputDir, typeMap);

            var xplmHeadersPath = Path.Combine(SdkRoot, "CHeaders", "XPLM");

            if (!Directory.Exists(xplmHeadersPath))
            {
                throw new DirectoryNotFoundException($"Directory '{xplmHeadersPath}' does not exist.");
            }
            var xmplHeaders = Directory.EnumerateFiles(xplmHeadersPath, "*.h");

            var xpWidgetsHeadersPath = Path.Combine(SdkRoot, "CHeaders", "Widgets");

            if (!Directory.Exists(xpWidgetsHeadersPath))
            {
                throw new DirectoryNotFoundException($"Directory '{xpWidgetsHeadersPath}' does not exist.");
            }
            var xpWidgetsHeaders = Directory.EnumerateFiles(xpWidgetsHeadersPath, "*.h");
            var headers          = xmplHeaders.Concat(xpWidgetsHeaders)
                                   /*.Where(x => Path.GetFileName(x) != "XPStandardWidgets.h")*/;

            var parserOptions = new CppParserOptions
            {
                Defines             = { "IBM", "XPLM303", "XPLM302", "XPLM301", "XPLM300", "XPLM210", "XPLM200" },
                ParseSystemIncludes = false,
                TargetCpu           = CppTargetCpu.X86_64,
                IncludeFolders      = { xplmHeadersPath },
            };


            var compilation = CppParser.ParseFiles(headers.ToList(), parserOptions);

            foreach (var child in compilation.Children().OfType <CppType>())
            {
                await BuildTypeAsync(child);
            }

            var functionsByHeader = compilation
                                    .Functions
                                    .ToLookup(x => x.Span.Start.File);

            foreach (var functionsInHeader in functionsByHeader)
            {
                await functionBuilder.BuildAsync(functionsInHeader);
            }

            foreach (var document in workspace.CurrentSolution.Projects.SelectMany(p => p.Documents))
            {
                var text = await document.GetTextAsync(cancellationToken);

                await using var writer = new StreamWriter(document.FilePath, false);
                text.Write(writer, cancellationToken);
            }

            return(0);

            async Task BuildTypeCallback(dynamic item)
            {
                using (Log.PushIdent())
                {
                    await BuildTypeAsync(item);
                }
            }
        }
Example #20
0
        public static unsafe void Main(string[] args)
        {
            // input (single header)
            string headerPath = Path.Combine(Environment.CurrentDirectory, "../../src/BindingsForNativeLib/SimdJsonNative/simdjson.h");

            // output
            string cgluePath    = Path.Combine(Environment.CurrentDirectory, "../../src/BindingsForNativeLib/SimdJsonNative/bindings.cpp");
            string bindingsPath = Path.Combine(Environment.CurrentDirectory, "../../src/BindingsForNativeLib/SimdJsonSharp.Bindings/Bindings.Generated.cs");


            var options = new CppParserOptions();

            options.ConfigureForWindowsMsvc(CppTargetCpu.X86_64);
            options.EnableMacros();
            options.AdditionalArguments.Add("-std=c++17");
            // TODO: test on macOS
            CppCompilation compilation = CppParser.ParseFile(headerPath, options);

            var csSb = new StringBuilder();

            csSb.AppendLine("// THIS FILE IS AUTOGENERATED!");
            csSb.AppendLine();
            csSb.AppendLine("using System;");
            csSb.AppendLine("using System.Runtime.InteropServices;");
            csSb.AppendLine();
            csSb.Append($"namespace {Namespace}\n{{");

            // Since we bind C++ we need to generate a DllImport-friendly C glue
            var cSb = new StringBuilder();

            cSb.AppendLine("// THIS FILE IS AUTOGENERATED!");
            cSb.AppendLine("#include \"simdjson.h\"");
            cSb.AppendLine();
            cSb.AppendLine("#if (defined WIN32 || defined _WIN32)");
            cSb.AppendLine("#define EXPORTS(returntype) extern \"C\" __declspec(dllexport) returntype __cdecl");
            cSb.AppendLine("#else");
            cSb.AppendLine("#define EXPORTS(returntype) extern \"C\" __attribute__((visibility(\"default\"))) returntype");
            cSb.AppendLine("#endif");

            List <CppClass> allClasses = compilation.GetAllClassesRecursively();

            _allClassNames = allClasses.Select(c => c.GetDisplayName()).ToList();

            foreach (CppClass cppClass in allClasses)
            {
                var csApiMethodsSb = new StringBuilder();
                var csDllImportsSb = new StringBuilder();

                string className = cppClass.Name;
                if (cppClass.Parent is CppClass parentClass)
                {
                    className = $"{parentClass.Name}::{className}";
                }

                if (_typesToIgnore.Contains(className))
                {
                    continue;
                }

                // prefix for all members
                string prefix = cppClass.Name + "_";

                cSb.AppendLine();
                cSb.AppendLine($"/* {className} */");


                IEnumerable <CppFunction> allFunctions = cppClass.Constructors.Take(1 /* HACK: take only first available ctors for now :) */).Concat(cppClass.Functions);
                foreach (CppFunction cppFunc in allFunctions)
                {
                    var argDefinitions = new List <string>();
                    var argInvocations = new List <string>();

                    // skip operators for now
                    if (cppFunc.IsOperator())
                    {
                        continue;
                    }

                    bool isStatic = cppFunc.StorageQualifier == CppStorageQualifier.Static;

                    string funcPrefix = prefix; // Class_function()
                    if (isStatic)
                    {
                        funcPrefix += "s_"; // Class_s_staticFunction()
                    }
                    if (!cppFunc.IsConstructor && !isStatic)
                    {
                        argDefinitions.Add($"{className}* target");
                    }

                    foreach (CppParameter cppParam in cppFunc.Parameters)
                    {
                        var type = cppParam.Type.GetDisplayName();

                        // method contains a parameter of type we don't support - skip the whole method (goto)
                        if (_typesToIgnore.Any(t => type.Contains(t)))
                        {
                            goto SKIP_FUNC;
                        }

                        string invocation = cppParam.Name;

                        // HACK: replace references with pointers (for classes)
                        if (type.EndsWith("&"))
                        {
                            type       = type.Remove(type.Length - 1) + "*";
                            invocation = "*" + invocation;
                        }

                        argDefinitions.Add($"{type} {cppParam.Name}");
                        argInvocations.Add(invocation);
                    }

                    string funcReturnType = cppFunc.IsConstructor ? $"{className}*" : cppFunc.ReturnType.GetDisplayName();
                    string finalFuncName  = $"{funcPrefix}{cppFunc.Name}";

                    // Func declaration
                    cSb.Append($"EXPORTS({funcReturnType}) {finalFuncName}({argDefinitions.AsCommaSeparatedStr()})");
                    cSb.Append(" {");

                    // Body
                    if (cppFunc.IsConstructor)
                    {
                        cSb.Append($" return new {className}({argInvocations.AsCommaSeparatedStr()});");
                    }
                    else
                    {
                        string returnStr    = cppFunc.ReturnType.IsVoid() ? " " : " return ";
                        string invokeTarget = "target->";
                        if (isStatic)
                        {
                            invokeTarget = className + "::";
                        }

                        cSb.Append($"{returnStr}{invokeTarget}{cppFunc.Name}({argInvocations.AsCommaSeparatedStr()});");
                    }

                    cSb.Append(" }");
                    cSb.AppendLine();

                    var(dllImports, apiMethods) = GenerateMethodCSharp(cppFunc, finalFuncName);
                    csDllImportsSb.AppendLine(dllImports);
                    csApiMethodsSb.AppendLine(apiMethods);

SKIP_FUNC:
                    continue;
                }

                // destructor
                cSb.Append($"EXPORTS(void) {prefix}Dispose({className}* target) {{ delete target; }}");
                cSb.AppendLine();

                // generate C# for this method:
                csSb.AppendLine(GenerateClassCSharp(cppClass, csDllImportsSb.ToString(), csApiMethodsSb.ToString()));
            }

            csSb.Append("}"); // end of namespace

            File.WriteAllText(cgluePath, cSb.ToString());
            File.WriteAllText(bindingsPath, csSb.ToString());
        }
Example #21
0
        public void TestBodySimple()
        {
            var opt = new CppParserOptions().EnableFunctionBodies();

            opt.ParseSystemIncludes = false;

            ParseAssert(@"
void function0();
int function1(int a, float b);
float function2(int);
int function3(int args_a, bool args_b){
    int local_b = 1234;
    float b = function2(args_a);
    local_b = function1(local_b, b);
    return local_b;
}
",
                        compilation =>
            {
                Assert.False(compilation.HasErrors);

                Assert.AreEqual(4, compilation.Functions.Count);

                {
                    var cppFunction = compilation.Functions[0];
                    Assert.AreEqual("function0", cppFunction.Name);
                    Assert.AreEqual(0, cppFunction.Parameters.Count);
                    Assert.AreEqual("void", cppFunction.ReturnType.ToString());

                    var cppFunction1 = compilation.FindByName <CppFunction>("function0");
                    Assert.AreEqual(cppFunction, cppFunction1);
                }

                {
                    var cppFunction = compilation.Functions[1];
                    Assert.AreEqual("function1", cppFunction.Name);
                    Assert.AreEqual(2, cppFunction.Parameters.Count);
                    Assert.AreEqual("a", cppFunction.Parameters[0].Name);
                    Assert.AreEqual(CppTypeKind.Primitive, cppFunction.Parameters[0].Type.TypeKind);
                    Assert.AreEqual(CppPrimitiveKind.Int, ((CppPrimitiveType)cppFunction.Parameters[0].Type).Kind);
                    Assert.AreEqual("b", cppFunction.Parameters[1].Name);
                    Assert.AreEqual(CppTypeKind.Primitive, cppFunction.Parameters[1].Type.TypeKind);
                    Assert.AreEqual(CppPrimitiveKind.Float, ((CppPrimitiveType)cppFunction.Parameters[1].Type).Kind);
                    Assert.AreEqual("int", cppFunction.ReturnType.ToString());

                    var cppFunction1 = compilation.FindByName <CppFunction>("function1");
                    Assert.AreEqual(cppFunction, cppFunction1);
                }
                {
                    var cppFunction = compilation.Functions[2];
                    Assert.AreEqual("function2", cppFunction.Name);
                    Assert.AreEqual(1, cppFunction.Parameters.Count);
                    Assert.AreEqual(string.Empty, cppFunction.Parameters[0].Name);
                    Assert.AreEqual(CppTypeKind.Primitive, cppFunction.Parameters[0].Type.TypeKind);
                    Assert.AreEqual(CppPrimitiveKind.Int, ((CppPrimitiveType)cppFunction.Parameters[0].Type).Kind);
                    Assert.AreEqual("float", cppFunction.ReturnType.ToString());

                    var cppFunction1 = compilation.FindByName <CppFunction>("function2");
                    Assert.AreEqual(cppFunction, cppFunction1);
                }
                {
                    var cppFunction = compilation.Functions[3];
                    Assert.AreEqual("function3", cppFunction.Name);
                    Assert.AreEqual(2, cppFunction.Parameters.Count);
                    Assert.AreEqual("args_a", cppFunction.Parameters[0].Name);
                    Assert.AreEqual(CppTypeKind.Primitive, cppFunction.Parameters[0].Type.TypeKind);
                    Assert.AreEqual(CppPrimitiveKind.Int, ((CppPrimitiveType)cppFunction.Parameters[0].Type).Kind);
                    Assert.AreEqual("int", cppFunction.ReturnType.ToString());

                    var cppFunction1 = compilation.FindByName <CppFunction>("function3");
                    Assert.AreEqual(cppFunction, cppFunction1);
                }
            }
                        , opt, false);
        }