diff --git a/README.md b/README.md index 26f8461..e04723f 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/csbindgen/src/builder.rs b/csbindgen/src/builder.rs index e647260..ba624a7 100644 --- a/csbindgen/src/builder.rs +++ b/csbindgen/src/builder.rs @@ -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, 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; diff --git a/csbindgen/src/type_meta.rs b/csbindgen/src/type_meta.rs index 7b68bdc..45e1389 100644 --- a/csbindgen/src/type_meta.rs +++ b/csbindgen/src/type_meta.rs @@ -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();