There are usually many pains involved in using the C Library with C#. Not only is it difficult to create bindings, but cross-platform builds are very difficult. In this day and age, you have to build for multiple platforms and architectures, windows, osx, linux, android, ios, each with x64, x86, arm.
[Rust](https://www.rust-lang.org/) has an excellent toolchain for cross-platform builds, as well as [cc crate](https://crates.io/crates/cc), [cmake crate](https://crates.io/crates/cmake) allow C source code to be integrated into the build. And [rust-bindgen](https://crates.io/crates/bindgen), which generates bindings from `.h`, is highly functional and very stable.
csbindgen can easily bring native C libraries into C# through Rust. csbindgen generates Rust extern code and C# DllImport code to work with C# from code generated from C by bindgen. With cc crate or cmake crate, C code is linked to the single rust native library.
Of course, you can also output pure FFI Rust code (or a wrapper layer to make it easier to bring C, C++ libraries into C#) to C#.
Getting Started
---
Install on `Cargo.toml` as `build-dependencies` and set up `bindgen::Builder` on `build.rs`.
```toml
[build-dependencies]
csbindgen = "0.1.1"
```
### C (to Rust) to C#
For example, build [lz4](https://github.com/lz4/lz4) compression library.
```rust
// using bindgen, generate binding code
bindgen::Builder::default()
.header("c/lz4/lz4.h")
.generate().unwrap()
.write_to_file("lz4.rs").unwrap();
// using cc, build and link c code
cc::Build::new().file("lz4.c").compile("lz4");
// csbindgen code, generate both rust ffi and C# dll import
csbindgen::Builder::default()
.input_bindgen_file("lz4.rs") // read from bindgen generated code
Adjust `rust_file_header` and `rust_method_type_path` to match your module configuration.
`method_filter` allows you to specify which methods to exclude; if unspecified, methods prefixed with `_` are excluded by default.
`rust_method_prefix` and `csharp_method_prefix` or `csharp_entry_point_prefix` must be adjusted to match the method name to be called.
`csharp_dll_name_if` is optional. If specified, `#if` allows two DllName to be specified, which is useful if the name must be `__Internal` at iOS build.
If the file path to be loaded needs to be changed depending on the operating system, the following load code can be used.
`csharp_c_long_convert` and `csharp_c_ulong_convert` configure how handles `c_long` and `c_ulong` to C# type. default is to `int` and `uint` because `LLP64` is 32bit representation but you can change it to 64bit or use [CLong](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.clong)/CULong struct after .NET 6.