Overview of C2CS
main.h) files. It produces .cs files without the use of AI, ensuring 100% predictable and repeatable output. This tool is used to bridge C code into C# environments.repository·main·Indexed 43 days ago
https://github.com/bottlenoselabs/c2csA deterministic code generator that converts C header files (.h) into C# bindings (.cs) without the use of AI. It provides a reliable workflow for creating interop layers between C and C#, utilizing a two-step process with c2ffi to extract platform-specific metadata into JSON files before generating the final C# code. C2CS supports a wide range of platforms including Windows, macOS, Linux, iOS, tvOS, and Android, and provides the Interop.Runtime namespace for idiomatic C-to-C# interoperability.
.h) files. It produces .cs files without the use of AI, ensuring 100% predictable and repeatable output. This tool is used to bridge C code into C# environments.Some platforms have system headers that are closed-source or have licenses prohibiting redistribution for cross-compilation. Because C headers can contain actual source code, you cannot simply copy them to a different OS to perform cross-compilation.
To solve this, C2CS uses a two-step workflow to decouple metadata extraction from code generation:
ast): Run the ast tool (part of c2ffi) on the host operating system where the target system headers are legally available (e.g., running on Windows to read Windows headers). This tool extracts metadata (bit-widths, function names, structs, enums, etc.) into a C FFI .json file. Crucially, this .json file does not contain any source code, only metadata.cs): Move the generated .json files to any other operating system and use the main c2cs program to read these files and generate the final C# code for your target platforms.When calling C platform code from a .NET application, you can choose between three primary interoperability patterns depending on your platform requirements and performance needs:
Used when the C library (.dll, .dylib, or .so) is an external file.
dlopen (Unix) or LoadLibrary (Windows), and functions are resolved via dlsym or GetProcAddress. This involves an extra level of indirection (using function pointers) and is the standard behavior for DllImport in JIT environments.NativeAOT in .NET 5+). This allows for direct platform invocation, which is more performant as it removes the indirection of the extra pointer. This requires the use of the [DllImport] attribute.Used when the C library (.lib or .a) is compiled directly into the executable.
When performing interoperability between C# and C (via P/Invoke), you should aim for pass-through marshalling to maximize performance and minimize complexity.
To achieve this, use blittable structs instead of classes.
classes for interop requires navigating complex and unintuitive default marshalling behaviors in Microsoft's CLR or Mono, which can lead to errors like double-frees.Note: When using blittable structs for interop, you are responsible for manual memory management (similar to C), as there are no hidden allocations or control flow performed by the CLR on your behalf.
The Platform Matrix defines the compatibility between target operating systems, architectures, and the required Software Development Environments (SDE) for generating C# code.
Key columns in the matrix:
🔓 or 🔒): Indicates if system headers can be distributed to other platforms under an open-source license (🔓) or if they must be manually made accessible to C2CS on the host platform (🔒).ARM64, X64, X86).MinGW, MSVC, XCode, Android Studio).Runtime.g.cs. This file contains the Interop.Runtime namespace, which provides helper structs, methods, and 'glue' code designed to make C-to-C# interoperability more idiomatic and easier to manage.To build the project from the repository, ensure you have the following prerequisites:
General Prerequisites:
git clone --recurse-submodules https://github.com/bottlenoselabs/c2cs.gitPlatform Specifics:
xcode-select --install), Xcode (from App Store), Homebrew, and CMake (brew install cmake).Build Commands:
dotnet build./C2CS.sln in Visual Studio or Rider.git clone --recurse-submodules https://github.com/bottlenoselabs/c2cs.git
dotnet buildTo generate C# bindings for a specific C library on a target platform, you must provide three key pieces of information to the generation process:
arch-vendor-os-environment (e.g., x86_64-pc-windows-msvc) that tells Clang how to interpret the C code for that specific platform..h files belonging to the target platform. You must provide the root directory of these files so Clang can resolve types and definitions correctly (e.g., ensuring uint64_t has the correct bit-width for the target OS).win-x64, linux-arm64) that matches the corresponding Clang target to ensure the resulting .NET application can run on the intended platform.C2CS is distributed as a .NET global tool. You must have the .NET 9 SDK installed to use it.
To install the latest stable release:
dotnet tool install bottlenoselabs.c2cs.tool --globalTo install the latest pre-release version (including builds from MyGet):
dotnet tool install bottlenoselabs.c2cs.tool --global --add-source https://www.myget.org/F/bottlenoselabs/api/v3/index.json --version "*-*"If the dotnet tool command fails to find a specific version you expect, try clearing your NuGet caches:
dotnet nuget locals all --cleardotnet tool install bottlenoselabs.c2cs.tool --globalTo generate C# bindings for a C library, follow this workflow:
Extract Platform FFIs: Use c2ffi to extract platform-specific Foreign Function Interfaces (FFIs). Use the extract command with a configuration file.
Example: c2ffi extract --config <config-file>.json
Merge FFIs: Once you have extracted the FFIs for all target platforms (e.g., Windows, macOS, Linux) into a directory, merge them into a single cross-platform FFI JSON file using c2ffi merge.
Example: c2ffi merge --inputDirectoryPath <directory> --outputFilePath <output>.json
Execute C2CS: Run the c2cs tool with a configuration file to generate the final C# bindings.
Example: c2cs --config <config-file>.json
c2cs --config config-generate-cs.jsonWhen a platform is marked as locked (🔒), the system header files cannot be distributed. You must make them manually accessible to C2CS on the host machine to read C code for that target.
If using the MSVC SDE, you must download and install the Windows SDKs. The important directories are typically located at:
%ProgramFiles(x86)%\Windows Kits\10\Include
To access SDKs for Apple platforms, you must install XCode via the App Store on Apple-branded hardware.
To access Android SDKs, you must install Android Studio.
By default, C2CS logs at the Information level. To enable Debug level logging, create an appsettings.json file in the directory where C2CS is running. You can customize the log format and verbosity using the following structure:
{
"Logging": {
"Console": {
"LogLevel": {
"Default": "Warning",
"C2CS": "Debug"
},
"FormatterOptions": {
"ColorBehavior": "Enabled",
"SingleLine": true,
"IncludeScopes": true,
"TimestampFormat": "yyyy-dd-MM HH:mm:ss ",
"UseUtcTimestamp": true
}
}
}
}{
"Logging": {
"Console": {
"LogLevel": {
"Default": "Warning",
"C2CS": "Debug"
}
}
}
}