### Install ClangSharpPInvokeGenerator .NET Tool Source: https://github.com/dotnet/clangsharp/blob/main/README.md Installs the ClangSharpPInvokeGenerator globally as a .NET tool. This is the recommended setup. ```bash dotnet tool install --global ClangSharpPInvokeGenerator ``` -------------------------------- ### Build libClangSharp on Linux Source: https://github.com/dotnet/clangsharp/blob/main/README.md Instructions for cloning the clangsharp repository and configuring its native build using CMake on Linux. Specify the relative path to the LLVM installation and use 'make install' to build. ```cmd git clone https://github.com/dotnet/clangsharp cd clangsharp mkdir -p artifacts/bin/native cd artifacts/bin/native cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install -DPATH_TO_LLVM=../../../../llvm-project/artifacts/install ../../../ make install ``` -------------------------------- ### Build libClangSharp on Windows Source: https://github.com/dotnet/clangsharp/blob/main/README.md Instructions for cloning the clangsharp repository and configuring its native build using CMake on Windows. Specify the absolute path to the LLVM installation. ```cmd git clone https://github.com/dotnet/clangsharp cd clangsharp mkdir artifacts/bin/native cd artifacts/bin/native cmake -DCMAKE_INSTALL_PREFIX=../install -DPATH_TO_LLVM=absolute/path/to/repos/llvm-project/artifacts/install -G "Visual Studio 17 2022" -A x64 -Thost=x64 ../../.. ``` -------------------------------- ### ClangSharpPInvokeGenerator CLI Tool Usage Source: https://context7.com/dotnet/clangsharp/llms.txt Install and use the `ClangSharpPInvokeGenerator` CLI tool for command-line binding generation. Recommended for repeatable builds using response files. ```bash # Install the tool globally dotnet tool install --global ClangSharpPInvokeGenerator # Minimal invocation ClangSharpPInvokeGenerator \ --file mylib.h \ --namespace MyLib.Interop \ --output ./generated \ --libraryPath mylib \ --language c++ \ --config latest-codegen generate-file-scoped-namespaces # Response file approach (recommended — check into source control) # generate.rsp: # --file # mylib.h # --namespace # MyLib.Interop # --output # ./generated # --libraryPath # mylib # --config # latest-codegen # multi-file # generate-macro-bindings # exclude-enum-operators # --prefixStrip # mylib_ # --remap # my_handle_t=MyHandle # --with-access-specifier # *=Internal ClangSharpPInvokeGenerator @generate.rsp # Print the current Clang/ClangSharp version ClangSharpPInvokeGenerator --version # List all available -c / --config options ClangSharpPInvokeGenerator --config help ``` -------------------------------- ### Clone and Build LLVM on Windows Source: https://github.com/dotnet/clangsharp/blob/main/README.md Steps to clone the LLVM project and configure its build using CMake on Windows with Visual Studio. Ensure to set the correct installation prefix and generator. ```cmd git clone --single-branch --branch llvmorg-21.1.8 https://github.com/llvm/llvm-project cd llvm-project mkdir artifacts/bin cd artifacts/bin cmake -DCMAKE_INSTALL_PREFIX=../install -DLLVM_ENABLE_PROJECTS=clang -G "Visual Studio 17 2022" -A x64 -Thost=x64 ../../llvm ``` -------------------------------- ### Clone and Build LLVM on Linux Source: https://github.com/dotnet/clangsharp/blob/main/README.md Steps to clone the LLVM project and configure its build using CMake on Linux. Supports Release build type and specifies installation prefix. Portable build options are also listed. ```bash git clone --single-branch --branch llvmorg-21.1.8 https://github.com/llvm/llvm-project cd llvm-project mkdir -p artifacts/bin cd artifacts/bin cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install -DLLVM_ENABLE_PROJECTS=clang ../../llvm make install ``` -------------------------------- ### Tokenize Source Code Range with ClangSharp Source: https://context7.com/dotnet/clangsharp/llms.txt Use CXTranslationUnit.Tokenize to get raw tokens from a source range for tasks like syntax highlighting. Ensure tokens are disposed using tu.DisposeTokens. ```csharp using ClangSharp.Interop; using var index = CXIndex.Create(); using var tu = CXTranslationUnit.Parse( index, "source.c", ["-x", "c"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None); CXFile file = tu.GetFile("source.c"); CXSourceLocation start = tu.GetLocation(file, 1, 1); CXSourceLocation end = tu.GetLocationForOffset(file, 512); CXSourceRange range = CXSourceRange.Create(start, end); Span tokens = tu.Tokenize(range); try { // Annotate tokens with the cursors they belong to var cursors = new CXCursor[tokens.Length]; tu.AnnotateTokens(tokens, cursors); for (int i = 0; i < tokens.Length; i++) { CXToken tok = tokens[i]; CXTokenKind kind = tok.Kind; string spelling = tu.GetTokenSpelling(tok); Console.WriteLine($"{kind,-20} {spelling}"); } } finally { tu.DisposeTokens(tokens); } ``` -------------------------------- ### Inspect CXCursor Properties Source: https://context7.com/dotnet/clangsharp/llms.txt Access numerous properties of a CXCursor to get information about its declaration and expression metadata. This includes identity, location, type, and C++ specific details. ```C# using ClangSharp.Interop; // Assume `cursor` is a FunctionDecl obtained via VisitChildren CXCursor cursor = /* ... */; // Identity and location Console.WriteLine(cursor.Spelling.ToString()); // "my_function" Console.WriteLine(cursor.DisplayName.ToString()); // "my_function(int, float)" Console.WriteLine(cursor.Mangling.ToString()); // "_Z11my_functionif" Console.WriteLine(cursor.KindSpelling.ToString()); // "FunctionDecl" Console.WriteLine(cursor.DeclKindSpelling); // "Function" Console.WriteLine(cursor.QualifiedName.ToString()); // "MyNamespace::my_function" CXSourceLocation loc = cursor.Location; loc.GetFileLocation(out CXFile file, out uint line, out uint col, out _); Console.WriteLine($"{file.Name} {line}:{col}"); // Type information CXType type = cursor.Type; Console.WriteLine(type.Spelling.ToString()); // "int (int, float)" Console.WriteLine(cursor.ResultType.Spelling.ToString()); // "int" Console.WriteLine(cursor.IsVariadic); // false // Function-specific Console.WriteLine(cursor.NumArguments); // 2 Console.WriteLine(cursor.GetArgument(0).Spelling.ToString()); // "a" Console.WriteLine(cursor.IsDefinition); // true Console.WriteLine(cursor.HasBody); // true // C++ specifics Console.WriteLine(cursor.CXXMethod_IsVirtual); // false Console.WriteLine(cursor.CXXMethod_IsConst); // false Console.WriteLine(cursor.IsExternC); // false ``` -------------------------------- ### Create a Clang Index with CXIndex.Create Source: https://context7.com/dotnet/clangsharp/llms.txt Initializes a Clang index context. Ensure the index is disposed when parsing is complete. Global options can be tuned for specific tasks like indexing. ```csharp using ClangSharp.Interop; // excludeDeclarationsFromPch: skip declarations already included via a PCH // displayDiagnostics: print Clang diagnostics to stderr automatically using var index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: true); // Optionally tune global options (thread-safety, crash recovery …) index.GlobalOptions = CXGlobalOptFlags.CXGlobalOpt_ThreadBackgroundPriorityForIndexing; // Direct path emission for debugging index.SetInvocationEmissionPathOption("/tmp/clang-invocations"); Console.WriteLine($"Index handle: 0x{index.Handle:x}"); // Output: Index handle: 0x7f8a1c002b40 (platform-dependent) ``` -------------------------------- ### Building libClangSharp Native Library Source: https://context7.com/dotnet/clangsharp/llms.txt Provides a multi-step process for compiling the native libClangSharp helper library. This requires building LLVM/Clang first, then libClangSharp against it, followed by building managed assemblies and running tests. ```bash # Step 1 — Build LLVM/Clang (Linux example, targeting llvmorg-21.1.8) git clone --single-branch --branch llvmorg-21.1.8 https://github.com/llvm/llvm-project cd llvm-project && mkdir -p artifacts/bin && cd artifacts/bin cmake -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=../install \ -DLLVM_ENABLE_PROJECTS=clang \ -DLLVM_ENABLE_TERMINFO=OFF \ -DLLVM_ENABLE_ZLIB=OFF \ ../../llvm make install -j$(nproc) # Step 2 — Build libClangSharp git clone https://github.com/dotnet/clangsharp cd clangsharp && mkdir -p artifacts/bin/native && cd artifacts/bin/native cmake -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=../install \ -DPATH_TO_LLVM=../../../../llvm-project/artifacts/install \ ../../../ make install -j$(nproc) # Step 3 — Build the managed assemblies cd /path/to/clangsharp dotnet build -c Release # Step 4 — Run tests dotnet test -c Release # Step 5 — Pack NuGet packages dotnet pack -c Release ``` -------------------------------- ### Using CXSourceLocation and CXSourceRange in C# Source: https://context7.com/dotnet/clangsharp/llms.txt Demonstrates how to create, decompose, and utilize source locations and ranges within C# using ClangSharp interop. Ensure ClangSharp is properly referenced. ```csharp using ClangSharp.Interop; using var index = CXIndex.Create(); using var tu = CXTranslationUnit.Parse( index, "src.cpp", ["-std=c++17"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None); CXFile file = tu.GetFile("src.cpp"); // Build a location from line/column CXSourceLocation loc = tu.GetLocation(file, line: 3, column: 1); // Decompose a location loc.GetFileLocation(out CXFile outFile, out uint line, out uint col, out uint offset); Console.WriteLine($"{outFile.Name}:{line}:{col} (offset {offset})"); loc.GetExpansionLocation(out _, out uint expLine, out uint expCol, out _); loc.GetSpellingLocation(out _, out uint spLine, out uint spCol, out _); Console.WriteLine($"Is from main file: {loc.IsFromMainFile}"); Console.WriteLine($"Is in system header: {loc.IsInSystemHeader}"); // Build a range from two locations CXSourceLocation end = tu.GetLocation(file, line: 3, column: 20); CXSourceRange range = CXSourceRange.Create(loc, end); Console.WriteLine($"Range null: {range.IsNull}"); // Use with a cursor's extent CXCursor cursor = tu.GetCursor(loc); CXSourceRange extent = cursor.Extent; extent.Start.GetFileLocation(out _, out uint startLine, out uint startCol, out _); extent.End.GetFileLocation(out _, out uint endLine, out uint endCol, out _); Console.WriteLine($"Cursor spans {startLine}:{startCol}–{endLine}:{endCol}"); ``` -------------------------------- ### CXIndex.Create Source: https://context7.com/dotnet/clangsharp/llms.txt `CXIndex` is the root context for all Clang parsing. `Create` wraps `clang_createIndex` and must be disposed when parsing is complete. It allows for optional configuration of global options and invocation emission paths. ```APIDOC ## CXIndex.Create — Create a Clang index ### Description `CXIndex` is the root context for all Clang parsing. `Create` wraps `clang_createIndex` and must be disposed when parsing is complete. ### Method `CXIndex.Create(bool excludeDeclarationsFromPch, bool displayDiagnostics) ### Parameters - **excludeDeclarationsFromPch** (bool) - Optional - If true, skips declarations already included via a PCH. - **displayDiagnostics** (bool) - Optional - If true, prints Clang diagnostics to stderr automatically. ### Request Example ```csharp using var index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: true); // Optionally tune global options (thread-safety, crash recovery …) index.GlobalOptions = CXGlobalOptFlags.CXGlobalOpt_ThreadBackgroundPriorityForIndexing; // Direct path emission for debugging index.SetInvocationEmissionPathOption("/tmp/clang-invocations"); Console.WriteLine($"Index handle: 0x{index.Handle:x}"); ``` ### Response #### Success Response - **CXIndex** - An instance of the Clang index context. ``` -------------------------------- ### Generate Bindings using Response File Source: https://github.com/dotnet/clangsharp/blob/main/README.md Executes the ClangSharpPInvokeGenerator using a response file. Response files allow for checking in command-line arguments. ```bash ClangSharpPInvokeGenerator @generate.rsp ``` -------------------------------- ### ClangSharpPInvokeGenerator Usage and Options Source: https://github.com/dotnet/clangsharp/blob/main/README.md Displays the usage information and all available command-line options for the ClangSharpPInvokeGenerator. Use these options to configure the binding generation process. ```bash ClangSharpPInvokeGenerator ClangSharp P/Invoke Binding Generator Usage: ClangSharpPInvokeGenerator [options] Options: -a, --additional An argument to pass to Clang when parsing the input files. [] -c, --config A configuration option that controls how the bindings are generated. Specify 'help' to see the available options. [] -D, --define-macro Define to (or 1 if omitted). [] -e, --exclude A declaration name to exclude from binding generation. [] -f, --file A file to parse and generate bindings for. [] -F, --file-directory The base path for files to parse. [] -hf, --headerFile A file which contains the header to prefix every generated file with. [] -i, --include A declaration name to include in binding generation. [] -I, --include-directory Add directory to include search path. [] -x, --language Treat subsequent input files as having type . [default: c++] -l, --libraryPath The string to use in the DllImport attribute used when generating bindings. [] -m, --methodClassName The name of the static class that will contain the generated method bindings. [default: Methods] -n, --namespace The namespace in which to place the generated bindings. [] -om, --output-mode The mode describing how the information collected from the headers are presented in the resultant bindings. [default: CSharp] -o, --output The output location to write the generated bindings to. [] -p, --prefixStrip The prefix to strip from the generated method bindings. [] --nativeTypeNamesToStrip The contents to strip from the generated NativeTypeName attributes. [] -r, --remap A declaration name to be remapped to another name during binding generation. [] -std Language standard to compile for. [] -to, --test-output The output location to write the generated tests to. [] -t, --traverse A file name included either directly or indirectly by -f that should be traversed during binding generation. [] -v, --version Prints the current version information for the tool and its native dependencies. -was, --with-access-specifier An access specifier to be used with the given qualified or remapped declaration name during binding generation. Supports wildcards. [] -wa, --with-attribute An attribute to be added to the given remapped declaration name during binding generation. Supports wildcards. [] -wcc, --with-callconv A calling convention to be used for the given declaration during binding generation. Supports wildcards. [] -wc, --with-class A class to be used for the given remapped constant or function declaration name during binding generation. Supports wildcards. [] ``` -------------------------------- ### Request Code Completion Suggestions with ClangSharp Source: https://context7.com/dotnet/clangsharp/llms.txt Utilize CXTranslationUnit.CodeCompleteAt to obtain IDE-style completion proposals at a specific source location. Remember to dispose of the results using clang.disposeCodeCompleteResults. ```csharp using ClangSharp.Interop; using var index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); using var tu = CXTranslationUnit.Parse( index, "code.cpp", ["-std=c++17"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_PrecompiledPreamble); // Request completions at line 10, column 5 in code.cpp CXCodeCompleteResults* results = tu.CodeCompleteAt( "code.cpp", 10, 5, ReadOnlySpan.Empty, CXCodeComplete_Flags.CXCodeComplete_IncludeMacros | CXCodeComplete_Flags.CXCodeComplete_IncludeCodePatterns); if (results != null) { try { Console.WriteLine($"{results->NumResults} completion candidates:"); for (uint i = 0; i < results->NumResults; i++) { CXCompletionResult result = results->Results[i]; CXCompletionString cs = result.CompletionString; Console.WriteLine($" [{result.CursorKind}] {cs.BriefComment}"); } } finally { clang.disposeCodeCompleteResults(results); } } ``` -------------------------------- ### Parse Source File with CXTranslationUnit.TryParse Source: https://context7.com/dotnet/clangsharp/llms.txt Parses a source file into a translation unit (AST). Handles potential parsing errors and iterates through diagnostics, printing errors to standard error. The translation unit must be disposed. ```csharp using ClangSharp.Interop; using var index = CXIndex.Create(); string[] args = ["-std=c++17", "-x", "c++"]; var flags = CXTranslationUnit_Flags.CXTranslationUnit_IncludeBriefCommentsInCodeCompletion | CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies; CXErrorCode error = CXTranslationUnit.TryParse( index, "my_header.h", args, ReadOnlySpan.Empty, flags, out CXTranslationUnit tu); if (error != CXErrorCode.CXError_Success) { Console.Error.WriteLine($"Parse failed: {error}"); return; } using (tu) { Console.WriteLine($"Parsed: {tu.Spelling}"); // "my_header.h" Console.WriteLine($"Diagnostics: {tu.NumDiagnostics}"); // Inspect every diagnostic for (uint i = 0; i < tu.NumDiagnostics; i++) { using var diag = tu.GetDiagnostic(i); if (diag.Severity >= CXDiagnosticSeverity.CXDiagnostic_Error) Console.Error.WriteLine(diag.Format(CXDiagnostic.DefaultDisplayOptions)); } } ``` -------------------------------- ### Programmatic P/Invoke Binding Generation with C# Source: https://context7.com/dotnet/clangsharp/llms.txt Use `PInvokeGenerator` to programmatically orchestrate the binding generation pipeline. Configure output, namespaces, and generation options before parsing headers and generating C# code. ```csharp using ClangSharp; using ClangSharp.Interop; using System.IO; var config = new PInvokeGeneratorConfiguration( language: "c", languageStandard: "c99", defaultNamespace: "MyC.Interop", outputLocation: "./output", headerFile: null, outputMode: PInvokeGeneratorOutputMode.CSharp, options: PInvokeGeneratorConfigurationOptions.GenerateLatestCode | PInvokeGeneratorConfigurationOptions.GenerateFileScopedNamespaces) { LibraryPath = "myc", }; // outputStreamFactory maps a logical file name → writable Stream Stream OutputFactory(string name) { Directory.CreateDirectory("./output"); return File.Open(Path.Combine("./output", name), FileMode.Create); } using var generator = new PInvokeGenerator(config, OutputFactory); // Parse and generate — one call per header file string[] clangArgs = ["-x", "c", "-std=c99", "-I/usr/include"]; generator.GenerateBindings( translationUnit: CXTranslationUnit.Parse( CXIndex.Create(), "mylib.h", clangArgs, ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies), filePath: "mylib.h", clangCommandLineArgs: clangArgs, translationFlags: CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies); // Collect diagnostics emitted during generation foreach (Diagnostic diag in generator.Diagnostics) { Console.WriteLine($"[{diag.Level}] {diag.Message}"); } ``` -------------------------------- ### Configure P/Invoke Binding Generator with ClangSharp Source: https://context7.com/dotnet/clangsharp/llms.txt Customize the PInvokeGenerator settings using PInvokeGeneratorConfiguration for output mode, namespaces, library paths, remappings, and access specifiers. Options can be combined using the bitwise OR operator. ```csharp using ClangSharp; using ClangSharp.Interop; var config = new PInvokeGeneratorConfiguration( language: "c++", languageStandard: "c++17", defaultNamespace: "MyLib.Interop", outputLocation: "./generated", headerFile: null, outputMode: PInvokeGeneratorOutputMode.CSharp, options: PInvokeGeneratorConfigurationOptions.GenerateLatestCode | PInvokeGeneratorConfigurationOptions.GenerateFileScopedNamespaces | PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles | PInvokeGeneratorConfigurationOptions.GenerateMacroBindings | PInvokeGeneratorConfigurationOptions.ExcludeEnumOperators) { LibraryPath = "mylib", DefaultClass = "NativeMethods", MethodPrefixToStrip = "mylib_", RemappedNames = new Dictionary { ["my_handle_t"] = "MyHandle" }, WithAccessSpecifiers = new Dictionary { ["*"] = AccessSpecifier.Internal // make everything internal }, TraversalNames = ["mylib.h"], // only traverse declarations in mylib.h ExcludedNames = ["mylib_internal_fn"], }; // Verify properties Console.WriteLine(config.GenerateLatestCode); // True Console.WriteLine(config.DefaultNamespace); // "MyLib.Interop" Console.WriteLine(config.LibraryPath); // "\"mylib\"" ``` -------------------------------- ### Run Local ClangSharpPInvokeGenerator Source: https://github.com/dotnet/clangsharp/blob/main/README.md Execute the locally built ClangSharpPInvokeGenerator executable. This command is for general use after building the project. ```bash artifacts/bin/sources/ClangSharpPInvokeGenerator/Debug/net6.0/ClangSharpPInvokeGenerator ``` -------------------------------- ### Run Local ClangSharpPInvokeGenerator on Linux Source: https://github.com/dotnet/clangsharp/blob/main/README.md Execute the locally built ClangSharpPInvokeGenerator on Linux, ensuring the dynamic library path is set correctly. This is necessary for the executable to find its dependencies. ```bash LD_LIBRARY_PATH=$(pwd)/artifacts/bin/native/lib/ artifacts/bin/sources/ClangSharpPInvokeGenerator/Debug/net6.0/ClangSharpPInvokeGenerator ``` -------------------------------- ### CXTranslationUnit.TryParse Source: https://context7.com/dotnet/clangsharp/llms.txt The primary entry point for turning C/C++ source into an Abstract Syntax Tree (AST). Returns a `CXErrorCode` and fills an `out` translation unit on success. Supports custom arguments and flags for parsing. ```APIDOC ## CXTranslationUnit.TryParse — Parse a source file into an AST ### Description The primary entry point for turning C/C++ source into an AST. Returns a `CXErrorCode` and fills an `out` translation unit on success. ### Method `CXTranslationUnit.TryParse(CXIndex index, string fileName, string[] commandLineArgs, ReadOnlySpan unsavedFiles, CXTranslationUnit_Flags flags, out CXTranslationUnit translationUnit) ### Parameters - **index** (CXIndex) - The Clang index context. - **fileName** (string) - The path to the source file to parse. - **commandLineArgs** (string[]) - An array of strings representing the command-line arguments for the C/C++ compiler. - **unsavedFiles** (ReadOnlySpan) - A span of `CXUnsavedFile` structures for in-memory source files. - **flags** (CXTranslationUnit_Flags) - Flags that control the parsing behavior. - **translationUnit** (out CXTranslationUnit) - An output parameter that will be filled with the parsed translation unit on success. ### Request Example ```csharp using var index = CXIndex.Create(); string[] args = ["-std=c++17", "-x", "c++"]; var flags = CXTranslationUnit_Flags.CXTranslationUnit_IncludeBriefCommentsInCodeCompletion | CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies; CXErrorCode error = CXTranslationUnit.TryParse( index, "my_header.h", args, ReadOnlySpan.Empty, flags, out CXTranslationUnit tu); if (error != CXErrorCode.CXError_Success) { Console.Error.WriteLine($"Parse failed: {error}"); return; } using (tu) { Console.WriteLine($"Parsed: {tu.Spelling}"); Console.WriteLine($"Diagnostics: {tu.NumDiagnostics}"); // Inspect every diagnostic for (uint i = 0; i < tu.NumDiagnostics; i++) { using var diag = tu.GetDiagnostic(i); if (diag.Severity >= CXDiagnosticSeverity.CXDiagnostic_Error) Console.Error.WriteLine(diag.Format(CXDiagnostic.DefaultDisplayOptions)); } } ``` ### Response #### Success Response (CXErrorCode.CXError_Success) - **CXTranslationUnit** - The parsed translation unit. - **CXErrorCode** - `CXErrorCode.CXError_Success` indicates successful parsing. ``` -------------------------------- ### PInvokeGeneratorConfiguration Source: https://context7.com/dotnet/clangsharp/llms.txt Configure the binding generator. This is the settings object for PInvokeGenerator, controlling output mode, namespace, library path, remappings, access specifiers, and generation options. ```APIDOC ## PInvokeGeneratorConfiguration ### Description Configure the binding generator. `PInvokeGeneratorConfiguration` is the settings object for `PInvokeGenerator`. All customisation — output mode, namespace, library path, remappings, access specifiers, and generation options — flows through this class. ### Class ```csharp public class PInvokeGeneratorConfiguration ``` ### Properties - **language** (string) - The language of the source code (e.g., "c++"). - **languageStandard** (string) - The language standard (e.g., "c++17"). - **defaultNamespace** (string) - The default namespace for generated code. - **outputLocation** (string) - The directory where generated files will be placed. - **headerFile** (string?) - Optional header file to process. - **outputMode** (PInvokeGeneratorOutputMode) - The output mode for the generator. - **options** (PInvokeGeneratorConfigurationOptions) - Options to configure generation behavior. - **libraryPath** (string?) - The path to the native library. - **defaultClass** (string?) - The default class name for native methods. - **methodPrefixToStrip** (string?) - A prefix to strip from native method names. - **remappedNames** (Dictionary?) - A dictionary for remapping type names. - **withAccessSpecifiers** (Dictionary?) - A dictionary to specify access specifiers for declarations. - **traversalNames** (IEnumerable?) - A list of names to traverse during generation. - **excludedNames** (IEnumerable?) - A list of names to exclude from generation. ### Request Example ```csharp using ClangSharp; using ClangSharp.Interop; var config = new PInvokeGeneratorConfiguration( language: "c++", languageStandard: "c++17", defaultNamespace: "MyLib.Interop", outputLocation: "./generated", headerFile: null, outputMode: PInvokeGeneratorOutputMode.CSharp, options: PInvokeGeneratorConfigurationOptions.GenerateLatestCode | PInvokeGeneratorConfigurationOptions.GenerateFileScopedNamespaces | PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles | PInvokeGeneratorConfigurationOptions.GenerateMacroBindings | PInvokeGeneratorConfigurationOptions.ExcludeEnumOperators) { LibraryPath = "mylib", DefaultClass = "NativeMethods", MethodPrefixToStrip = "mylib_", RemappedNames = new Dictionary { ["my_handle_t"] = "MyHandle" }, WithAccessSpecifiers = new Dictionary { ["*"] = AccessSpecifier.Internal // make everything internal }, TraversalNames = ["mylib.h"], // only traverse declarations in mylib.h ExcludedNames = ["mylib_internal_fn"], }; // Verify properties Console.WriteLine(config.GenerateLatestCode); // True Console.WriteLine(config.DefaultNamespace); // "MyLib.Interop" Console.WriteLine(config.LibraryPath); // "\"mylib\"" ``` ``` -------------------------------- ### Traverse AST Recursively with CXCursor.VisitChildren Source: https://context7.com/dotnet/clangsharp/llms.txt Use CXCursor.VisitChildren to recursively traverse the AST. You can provide a managed delegate or an unmanaged function pointer as the callback. The callback receives the current cursor, its parent, and client data. ```C# using ClangSharp.Interop; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using var index = CXIndex.Create(); using var tu = CXTranslationUnit.Parse( index, "header.h", ["-std=c++17"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None); // Managed delegate version (allocates a GCHandle internally) tu.Cursor.VisitChildren((cursor, parent, clientData) => { string indent = new string(' ', (int)(nuint)clientData * 2); Console.WriteLine($"{indent}[{cursor.KindSpelling}] {cursor.Spelling}"); // Recurse into children by returning Recurse return CXChildVisitResult.CXChildVisit_Recurse; }, clientData: (CXClientData)(nuint)0); // Low-overhead unmanaged function pointer version [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] static CXChildVisitResult Visitor(CXCursor cursor, CXCursor parent, void* data) { _ = Console.Out.WriteLineAsync(cursor.Spelling.ToString()); return CXChildVisitResult.CXChildVisit_Continue; } tu.Cursor.VisitChildren(&Visitor, default); ``` -------------------------------- ### CXCursor.VisitChildren Source: https://context7.com/dotnet/clangsharp/llms.txt Traverse the AST recursively by supplying a callback that receives each cursor and its parent. Supports both managed delegates and unmanaged function pointers. ```APIDOC ## `CXCursor.VisitChildren` — Traverse the AST recursively The fundamental AST traversal primitive. Supply an `unmanaged` callback (or a managed delegate) that receives each cursor and its parent. ```csharp using ClangSharp.Interop; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using var index = CXIndex.Create(); using var tu = CXTranslationUnit.Parse( index, "header.h", ["-std=c++17"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None); // Managed delegate version (allocates a GCHandle internally) tu.Cursor.VisitChildren((cursor, parent, clientData) => { string indent = new string(' ', (int)(nuint)clientData * 2); Console.WriteLine($"{{indent}}[{{cursor.KindSpelling}}] {{cursor.Spelling}}"); // Recurse into children by returning Recurse return CXChildVisitResult.CXChildVisit_Recurse; }, clientData: (CXClientData)(nuint)0); // Low-overhead unmanaged function pointer version [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] static CXChildVisitResult Visitor(CXCursor cursor, CXCursor parent, void* data) { _ = Console.Out.WriteLineAsync(cursor.Spelling.ToString()); return CXChildVisitResult.CXChildVisit_Continue; } tu.Cursor.VisitChildren(&Visitor, default); ``` ``` -------------------------------- ### High-level AST Traversal with ClangSharp OO API Source: https://context7.com/dotnet/clangsharp/llms.txt Utilize the `ClangSharp` namespace's managed objects to navigate the Clang C++ Abstract Syntax Tree (AST). `TranslationUnit.GetOrCreate` is the entry point for obtaining a managed `TranslationUnit` from a `CXTranslationUnit`. ```csharp using ClangSharp; using ClangSharp.Interop; // Obtain a managed TranslationUnit from a CXTranslationUnit using var index = CXIndex.Create(); CXTranslationUnit cxTu = CXTranslationUnit.Parse( index, "sample.cpp", ["-std=c++17"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None); TranslationUnit tu = TranslationUnit.GetOrCreate(cxTu); // Root cursor is a TranslationUnitDecl Cursor root = tu.TranslationUnitDecl; Console.WriteLine(root.CursorKindSpelling); // "TranslationUnit" // Walk direct children using the managed CursorChildren collection foreach (Cursor child in root.CursorChildren) { Console.WriteLine($"{child.CursorKindSpelling}: {child.Spelling}"); // Pattern-match on the Clang C++ type hierarchy if (child is FunctionDecl fn) { Console.WriteLine($" return type : {fn.ReturnType.AsString}"); Console.WriteLine($" param count : {fn.Parameters.Count}"); Console.WriteLine($" is variadic : {fn.IsVariadic}"); Console.WriteLine($" has body : {fn.HasBody}"); } else if (child is RecordDecl record) { Console.WriteLine($" fields: {record.Fields.Count}"); } else if (child is EnumDecl enumDecl) { foreach (EnumConstantDecl constant in enumDecl.Enumerators) Console.WriteLine($" {constant.Spelling} = {constant.InitVal}"); } } ``` -------------------------------- ### CXTranslationUnit.CreateFromSourceFile Source: https://context7.com/dotnet/clangsharp/llms.txt Allows parsing source code that has not been written to disk, which is useful for tooling and IDE integrations. It takes the source content directly in memory. ```APIDOC ## CXTranslationUnit.CreateFromSourceFile — Parse with unsaved (in-memory) files ### Description Allows parsing source that has not been written to disk, useful for tooling and IDE integrations. ### Method `CXTranslationUnit.CreateFromSourceFile(CXIndex index, string fileName, string[] commandLineArgs, CXUnsavedFile[] unsavedFiles) ### Parameters - **index** (CXIndex) - The Clang index context. - **fileName** (string) - The name of the virtual file to be used for the source code. - **commandLineArgs** (string[]) - An array of strings representing the command-line arguments for the C/C++ compiler. - **unsavedFiles** (CXUnsavedFile[]) - An array of `CXUnsavedFile` structures containing the source code content. ### Request Example ```csharp using var index = CXIndex.Create(); // Provide source content in memory without writing to disk string sourceCode = "int add(int a, int b) { return a + b; }"; byte[] bytes = Encoding.UTF8.GetBytes(sourceCode); var unsavedFiles = new CXUnsavedFile[] { CXUnsavedFile.Create("virtual.c", sourceCode) }; var tu = CXTranslationUnit.CreateFromSourceFile( index, "virtual.c", ["-x", "c"], unsavedFiles); using (tu) { CXCursor root = tu.Cursor; Console.WriteLine($"TU kind: {root.KindSpelling}"); // "TranslationUnit" Console.WriteLine($"Children: {root.NumChildren}"); // 1 (the FunctionDecl) } ``` ### Response #### Success Response - **CXTranslationUnit** - The parsed translation unit. ``` -------------------------------- ### CXTranslationUnit.CodeCompleteAt Source: https://context7.com/dotnet/clangsharp/llms.txt Request code completion suggestions. Provides IDE-style completion proposals at a given source position. ```APIDOC ## CXTranslationUnit.CodeCompleteAt ### Description Provides IDE-style completion proposals at a given source position. ### Method ```csharp CXCodeCompleteResults* CodeCompleteAt(string filename, int line, int column, ReadOnlySpan unsavedFiles, CXCodeComplete_Flags flags) ``` ### Parameters #### Path Parameters - **filename** (string) - The name of the file where completion is requested. - **line** (int) - The line number for completion. - **column** (int) - The column number for completion. - **unsavedFiles** (ReadOnlySpan) - A span of unsaved files. - **flags** (CXCodeComplete_Flags) - Flags to control code completion behavior. ### Request Example ```csharp using ClangSharp.Interop; using var index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); using var tu = CXTranslationUnit.Parse( index, "code.cpp", ["-std=c++17"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_PrecompiledPreamble); // Request completions at line 10, column 5 in code.cpp CXCodeCompleteResults* results = tu.CodeCompleteAt( "code.cpp", 10, 5, ReadOnlySpan.Empty, CXCodeComplete_Flags.CXCodeComplete_IncludeMacros | CXCodeComplete_Flags.CXCodeComplete_IncludeCodePatterns); if (results != null) { try { Console.WriteLine($"{results->NumResults} completion candidates:"); for (uint i = 0; i < results->NumResults; i++) { CXCompletionResult result = results->Results[i]; CXCompletionString cs = result.CompletionString; Console.WriteLine($" [{{result.CursorKind}}] {{cs.BriefComment}}"); } } finally { clang.disposeCodeCompleteResults(results); } } ``` ``` -------------------------------- ### Parse In-Memory Source with CXTranslationUnit.CreateFromSourceFile Source: https://context7.com/dotnet/clangsharp/llms.txt Parses source code provided directly in memory without writing to disk, suitable for dynamic analysis or IDE integrations. The translation unit must be disposed. ```csharp using ClangSharp.Interop; using System.Text; using var index = CXIndex.Create(); // Provide source content in memory without writing to disk string sourceCode = "int add(int a, int b) { return a + b; }"; byte[] bytes = Encoding.UTF8.GetBytes(sourceCode); var unsavedFiles = new CXUnsavedFile[] { CXUnsavedFile.Create("virtual.c", sourceCode) }; var tu = CXTranslationUnit.CreateFromSourceFile( index, "virtual.c", ["-x", "c"], unsavedFiles); using (tu) { CXCursor root = tu.Cursor; Console.WriteLine($"TU kind: {root.KindSpelling}"); // "TranslationUnit" Console.WriteLine($"Children: {root.NumChildren}"); // 1 (the FunctionDecl) } ``` -------------------------------- ### CXTranslationUnit.Tokenize Source: https://context7.com/dotnet/clangsharp/llms.txt Lexically tokenize a source range. Returns the raw token stream covering a source range, useful for syntax highlighting or comment extraction. ```APIDOC ## CXTranslationUnit.Tokenize ### Description Lexically tokenize a source range. Returns the raw token stream covering a source range, useful for syntax highlighting or comment extraction. ### Method ```csharp Span Tokenize(CXSourceRange range) ``` ### Parameters #### Path Parameters - **range** (CXSourceRange) - The source range to tokenize. ### Request Example ```csharp using ClangSharp.Interop; using var index = CXIndex.Create(); using var tu = CXTranslationUnit.Parse( index, "source.c", ["-x", "c"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None); CXFile file = tu.GetFile("source.c"); CXSourceLocation start = tu.GetLocation(file, 1, 1); CXSourceLocation end = tu.GetLocationForOffset(file, 512); CXSourceRange range = CXSourceRange.Create(start, end); Span tokens = tu.Tokenize(range); try { // ... process tokens ... } finally { tu.DisposeTokens(tokens); } ``` ``` -------------------------------- ### CXDiagnostic Source: https://context7.com/dotnet/clangsharp/llms.txt Access parse-time diagnostics (errors, warnings, notes) produced during parsing. Includes details like severity, message, location, and suggested fix-its. ```APIDOC ## `CXDiagnostic` — Access parse-time diagnostics Diagnostics (errors, warnings, notes) produced during parsing are accessible from the translation unit. ```csharp using ClangSharp.Interop; using var index = CXIndex.Create(); using var tu = CXTranslationUnit.Parse( index, "bad.h", ["-std=c++17"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord); for (uint i = 0; i < tu.NumDiagnostics; i++) { using CXDiagnostic diag = tu.GetDiagnostic(i); CXDiagnosticSeverity severity = diag.Severity; string message = diag.Spelling.ToString(); string category = diag.CategoryText.ToString(); CXSourceLocation loc = diag.Location; loc.GetFileLocation(out CXFile file, out uint line, out uint col, out _); Console.WriteLine($"[{{severity}}] {{file.Name}}:{line}:{col} — {{message}} ({{category}})"); // Suggested fix-its for (uint f = 0; f < diag.NumFixIts; f++) { CXString fixIt = diag.GetFixIt(f, out CXSourceRange range); Console.WriteLine($" Fix: replace with '{{fixIt}}'"); } // Format full diagnostic string the way clang would print it string formatted = diag.Format( CXDiagnosticDisplayOptions.CXDiagnostic_DisplaySourceLocation | CXDiagnosticDisplayOptions.CXDiagnostic_DisplayColumn).ToString(); Console.WriteLine(formatted); } ``` ``` -------------------------------- ### CXCursor properties Source: https://context7.com/dotnet/clangsharp/llms.txt Inspect declaration and expression metadata using `CXCursor` properties. These properties provide access to identity, location, type information, and C++ specific details. ```APIDOC ## `CXCursor` properties — Inspect declaration and expression metadata `CXCursor` exposes hundreds of properties backed by `libclang` and the supplementary `libClangSharp` native library. ```csharp using ClangSharp.Interop; // Assume `cursor` is a FunctionDecl obtained via VisitChildren CXCursor cursor = /* ... */; // Identity and location Console.WriteLine(cursor.Spelling.ToString()); // "my_function" Console.WriteLine(cursor.DisplayName.ToString()); // "my_function(int, float)" Console.WriteLine(cursor.Mangling.ToString()); // "_Z11my_functionif" Console.WriteLine(cursor.KindSpelling.ToString()); // "FunctionDecl" Console.WriteLine(cursor.DeclKindSpelling); // "Function" Console.WriteLine(cursor.QualifiedName.ToString()); // "MyNamespace::my_function" CXSourceLocation loc = cursor.Location; loc.GetFileLocation(out CXFile file, out uint line, out uint col, out _); Console.WriteLine($"{file.Name} {line}:{col}"); // Type information CXType type = cursor.Type; Console.WriteLine(type.Spelling.ToString()); // "int (int, float)" Console.WriteLine(cursor.ResultType.Spelling.ToString()); // "int" Console.WriteLine(cursor.IsVariadic); // false // Function-specific Console.WriteLine(cursor.NumArguments); // 2 Console.WriteLine(cursor.GetArgument(0).Spelling.ToString()); // "a" Console.WriteLine(cursor.IsDefinition); // true Console.WriteLine(cursor.HasBody); // true // C++ specifics Console.WriteLine(cursor.CXXMethod_IsVirtual); // false Console.WriteLine(cursor.CXXMethod_IsConst); // false Console.WriteLine(cursor.IsExternC); // false ``` ``` -------------------------------- ### Access Parse-Time Diagnostics with CXDiagnostic Source: https://context7.com/dotnet/clangsharp/llms.txt Retrieve and process diagnostics (errors, warnings, notes) generated during parsing from the translation unit. This includes severity, message, location, suggested fix-its, and formatted output. ```C# using ClangSharp.Interop; using var index = CXIndex.Create(); using var tu = CXTranslationUnit.Parse( index, "bad.h", ["-std=c++17"], ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord); for (uint i = 0; i < tu.NumDiagnostics; i++) { using CXDiagnostic diag = tu.GetDiagnostic(i); CXDiagnosticSeverity severity = diag.Severity; string message = diag.Spelling.ToString(); string category = diag.CategoryText.ToString(); CXSourceLocation loc = diag.Location; loc.GetFileLocation(out CXFile file, out uint line, out uint col, out _); Console.WriteLine($"[{severity}] {file.Name}:{line}:{col} — {message} ({category})"); // Suggested fix-its for (uint f = 0; f < diag.NumFixIts; f++) { CXString fixIt = diag.GetFixIt(f, out CXSourceRange range); Console.WriteLine($" Fix: replace with '{fixIt}'"); } // Format full diagnostic string the way clang would print it string formatted = diag.Format( CXDiagnosticDisplayOptions.CXDiagnostic_DisplaySourceLocation | CXDiagnosticDisplayOptions.CXDiagnostic_DisplayColumn).ToString(); Console.WriteLine(formatted); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.