Added option to avoid nint/nuint types (compatibility with older C# versions).

The option is called `csharp_use_nint_types` and defaults to `true`.
	Setting it as `false` will cause csbindgen to map the appropriate types
	to `System.IntPtr` and `System.UIntPtr` (the .NET aliases for `nint` and
	`nuint`) that are supported by all C# versions.
This commit is contained in:
Marco Mastropaolo 2023-09-14 16:08:18 +02:00
parent 8861b83a97
commit 9eb88e4b34
3 changed files with 36 additions and 8 deletions

View File

@ -488,8 +488,21 @@ Rust types will map these C# types.
csbindgen is designed to return primitives that do not cause marshalling. It is better to convert from pointers to Span yourself than to do the conversion implicitly and in a black box. This is a recent trend, such as the addition of [DisableRuntimeMarshalling](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.disableruntimemarshallingattribute) from .NET 7.
Older C# version do not support `nint` and `nuint`. You can use `csharp_use_nint_types` to use `IntPtr` and `UIntPtr` in their place:
```rust
csbindgen::Builder::default()
.input_extern_file("lib.rs")
.csharp_dll_name("nativelib")
.generate_csharp_file("../dotnet/NativeMethods.g.cs")
.csharp_use_nint_types(false)
.unwrap();
```
`c_long` and `c_ulong` will convert to [CLong](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.clong), [CULong](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.culong) struct after .NET 6. If you want to convert in Unity, you will need Shim.
```csharp
// Currently Unity is .NET Standard 2.1 so does not exist CLong and CULong
namespace System.Runtime.InteropServices

View File

@ -29,6 +29,7 @@ pub struct BindgenOptions {
pub csharp_if_symbol: String,
pub csharp_if_dll_name: String,
pub csharp_use_function_pointer: bool,
pub csharp_use_nint_types: bool,
pub csharp_imported_namespaces: Vec<String>,
pub csharp_generate_const_filter: fn(const_name: &str) -> bool,
}
@ -53,6 +54,7 @@ impl Default for Builder {
csharp_if_symbol: "".to_string(),
csharp_if_dll_name: "".to_string(),
csharp_use_function_pointer: true,
csharp_use_nint_types: true,
csharp_imported_namespaces: vec![],
csharp_generate_const_filter: |_| false,
},
@ -85,7 +87,7 @@ impl Builder {
self
}
/// add original extern call type prefix to rust wrapper,
/// `return {rust_method_type_path}::foo()`
@ -185,13 +187,20 @@ impl Builder {
self
}
/// configure C# usage of `nint`/`nuint` in place of `System.IntPtr`/`System.UIntPtr`, default is true
/// (use `nint`/`nuint`)
pub fn csharp_use_nint_types(mut self, csharp_use_nint_types: bool) -> Builder {
self.options.csharp_use_nint_types = csharp_use_nint_types;
self
}
/// configure C# generate const, default is false
/// equivalent to csharp_generate_const_filter(|_| csharp_generate_const)
#[deprecated(note = "User csharp_generate_const_filter instead")]
pub fn csharp_generate_const(mut self, csharp_generate_const: bool) -> Builder {
self.csharp_generate_const_filter(if csharp_generate_const { |_| true } else { |_| false })
}
/// configure C# generate const filter, default `|_| false`
pub fn csharp_generate_const_filter(mut self, csharp_generate_const_filter: fn(const_name: &str) -> bool) -> Builder {
self.options.csharp_generate_const_filter = csharp_generate_const_filter;

View File

@ -214,8 +214,10 @@ impl RustType {
method_name: &String,
parameter_name: &String,
) -> String {
fn convert_type_name(type_name: &str) -> String {
fn convert_type_name(type_name: &str, options: &BindgenOptions) -> String {
let temp_string: String;
let use_nint_types = options.csharp_use_nint_types;
let name = match type_name {
// rust primitives
"i8" => "sbyte",
@ -223,7 +225,8 @@ impl RustType {
"i32" => "int",
"i64" => "long",
"i128" => "Int128", // .NET 7
"isize" => "nint", // C# 9.0
"isize" if use_nint_types => "nint", // C# 9.0
"isize" => "System.IntPtr", // C# 9.0
"u8" => "byte",
"u16" => "ushort",
"u32" => "uint",
@ -233,7 +236,8 @@ impl RustType {
"f64" => "double",
"bool" => "bool",
"char" => "uint",
"usize" => "nuint", // C# 9.0
"usize" if use_nint_types => "nuint", // C# 9.0
"usize" => "System.UIntPtr",
"()" => "void",
// std::os::raw https://doc.rust-lang.org/std/os/raw/index.html
// std::ffi::raw https://doc.rust-lang.org/core/ffi/index.html
@ -258,13 +262,15 @@ impl RustType {
"NonZeroI32" => "int",
"NonZeroI64" => "long",
"NonZeroI128" => "Int128",
"NonZeroIsize" => "nint",
"NonZeroIsize" if use_nint_types => "nint",
"NonZeroIsize" => "System.IntPtr",
"NonZeroU8" => "byte",
"NonZeroU16" => "ushort",
"NonZeroU32" => "uint",
"NonZeroU64" => "ulong",
"NonZeroU128" => "UInt128",
"NonZeroUsize" => "nuint",
"NonZeroUsize" if use_nint_types => "nuint",
"NonZeroUsize" => "System.UIntPtr",
_ => {
temp_string = escape_name(type_name);
temp_string.as_str()
@ -289,7 +295,7 @@ impl RustType {
parameter_name,
)
} else {
convert_type_name(use_type.type_name.as_str()).to_string()
convert_type_name(use_type.type_name.as_str(), options).to_string()
};
let mut sb = String::new();