diff --git a/csbindgen/src/emitter.rs b/csbindgen/src/emitter.rs index 9b8a798..08be243 100644 --- a/csbindgen/src/emitter.rs +++ b/csbindgen/src/emitter.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use crate::alias_map::AliasMap; use crate::builder::BindgenOptions; use crate::type_meta::ExportSymbolNaming::{ExportName, NoMangle}; @@ -88,6 +90,7 @@ pub fn emit_csharp( let class_name = &options.csharp_class_name; let method_prefix = &options.csharp_method_prefix; let accessibility = &options.csharp_class_accessibility; + let mut forward_decls: HashSet = HashSet::new(); let mut dll_name = match options.csharp_if_symbol.as_str() { "" => format!( @@ -126,6 +129,7 @@ pub fn emit_csharp( aliases, method_name, &"return".to_string(), + &mut forward_decls, ) { method_list_string.push_str( format!(" [UnmanagedFunctionPointer(CallingConvention.Cdecl)]\n") @@ -143,6 +147,7 @@ pub fn emit_csharp( aliases, method_name, &p.name, + &mut forward_decls, ) { method_list_string.push_str( format!(" [UnmanagedFunctionPointer(CallingConvention.Cdecl)]\n") @@ -164,7 +169,7 @@ pub fn emit_csharp( }; let return_type = match &item.return_type { Some(x) => { - x.to_csharp_string(options, aliases, false, method_name, &"return".to_string()) + x.to_csharp_string(options, aliases, false, method_name, &"return".to_string(), &mut forward_decls) } None => "void".to_string(), }; @@ -175,7 +180,7 @@ pub fn emit_csharp( .map(|p| { let mut type_name = p.rust_type - .to_csharp_string(options, aliases, false, method_name, &p.name); + .to_csharp_string(options, aliases, false, method_name, &p.name, &mut forward_decls); if type_name == "bool" { type_name = "[MarshalAs(UnmanagedType.U1)] bool".to_string(); } @@ -226,6 +231,7 @@ pub fn emit_csharp( true, &"".to_string(), &"".to_string(), + &mut forward_decls, ); let attr = if type_name == "bool" { "[MarshalAs(UnmanagedType.U1)] ".to_string() @@ -304,6 +310,7 @@ pub fn emit_csharp( false, &"".to_string(), &"".to_string(), + &mut forward_decls, ); // special case for string, char, ByteStr @@ -347,6 +354,8 @@ pub fn emit_csharp( let class_string = if method_list_string.is_empty() && const_string.is_empty() { String::new() } else { + let forward_decls_string = forward_decls.drain().collect::>().join("\n"); + format!( "{accessibility} static unsafe partial class {class_name} {{ @@ -355,6 +364,8 @@ pub fn emit_csharp( {const_string} {method_list_string} + +{forward_decls_string} }}" ) }; diff --git a/csbindgen/src/type_meta.rs b/csbindgen/src/type_meta.rs index 534d1ff..d846ad4 100644 --- a/csbindgen/src/type_meta.rs +++ b/csbindgen/src/type_meta.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use crate::{alias_map::AliasMap, builder::BindgenOptions}; pub fn escape_csharp_name(str: &str) -> String { @@ -228,6 +230,7 @@ impl RustType { emit_from_struct: bool, method_name: &String, parameter_name: &String, + forward_decls: &mut HashSet, ) -> String { fn convert_type_name(type_name: &str, options: &BindgenOptions) -> String { let temp_string: String; @@ -308,6 +311,7 @@ impl RustType { emit_from_struct, method_name, parameter_name, + forward_decls, ) } else { convert_type_name(use_type.type_name.as_str(), options).to_string() @@ -347,6 +351,7 @@ impl RustType { emit_from_struct, method_name, parameter_name, + forward_decls, )); sb.push_str(", "); } @@ -358,6 +363,7 @@ impl RustType { emit_from_struct, method_name, parameter_name, + forward_decls, )); } None => { @@ -366,7 +372,15 @@ impl RustType { }; sb.push('>'); } else { - sb.push_str(build_method_delegate_name(method_name, parameter_name).as_str()); + let delegate_name = build_method_delegate_name(method_name, parameter_name); + + sb.push_str(&delegate_name); + + let decl = build_method_delegate_if_required(self, options, alias_map, method_name, parameter_name, forward_decls); + + if let Some(decl) = decl { + forward_decls.insert(format!(" [UnmanagedFunctionPointer(CallingConvention.Cdecl)]\n public {decl};")); + } } } TypeKind::Option(inner) => { @@ -379,6 +393,7 @@ impl RustType { emit_from_struct, method_name, parameter_name, + forward_decls, ) .as_str(), ); @@ -393,6 +408,7 @@ impl RustType { method_name: &String, parameter_name: &String, emit_inner: bool, + forward_decls: &mut HashSet, ) -> bool { use PointerType::*; if let TypeKind::Pointer(p, inner) = &rust_type.type_kind { @@ -405,6 +421,7 @@ impl RustType { emit_from_struct, method_name, parameter_name, + forward_decls, ) .as_str(), ); @@ -436,6 +453,7 @@ impl RustType { method_name, parameter_name, emit_inner, + forward_decls, ) { sb.push_str(type_csharp_string.as_str()); } @@ -452,6 +470,7 @@ impl RustType { method_name, parameter_name, emit_inner, + forward_decls, ) { if emit_inner { sb.push_str(type_csharp_string.as_str()); @@ -470,6 +489,7 @@ pub fn build_method_delegate_if_required( alias_map: &AliasMap, method_name: &String, parameter_name: &String, + forward_decls: &mut HashSet, ) -> Option { let emit_from_struct = false; @@ -487,6 +507,7 @@ pub fn build_method_delegate_if_required( emit_from_struct, method_name, parameter_name, + forward_decls, ), None => "void".to_string(), }; @@ -501,6 +522,7 @@ pub fn build_method_delegate_if_required( emit_from_struct, method_name, parameter_name, + forward_decls, ); let parameter_name = if p.name == "" { format!("arg{}", index + 1) @@ -525,6 +547,7 @@ pub fn build_method_delegate_if_required( alias_map, method_name, parameter_name, + forward_decls, ), _ => None, } diff --git a/dotnet-sandbox/NativeMethods.cs b/dotnet-sandbox/NativeMethods.cs index 57553be..ed33675 100644 --- a/dotnet-sandbox/NativeMethods.cs +++ b/dotnet-sandbox/NativeMethods.cs @@ -181,6 +181,8 @@ internal static unsafe partial class NativeMethods internal static extern void free_treat_as_empty_struct_context(TreatAsEmptyStruct* _src); + + } [StructLayout(LayoutKind.Sequential)] diff --git a/dotnet-sandbox/NestedModuleTests.cs b/dotnet-sandbox/NestedModuleTests.cs index a0e09ce..e4af7c4 100644 --- a/dotnet-sandbox/NestedModuleTests.cs +++ b/dotnet-sandbox/NestedModuleTests.cs @@ -26,6 +26,8 @@ internal static unsafe partial class NestedModuleTests internal static extern int number_map(NumberEnum input); + + } [StructLayout(LayoutKind.Sequential)] diff --git a/dotnet-sandbox/bullet3_bindgen.cs b/dotnet-sandbox/bullet3_bindgen.cs index c71990e..260b897 100644 --- a/dotnet-sandbox/bullet3_bindgen.cs +++ b/dotnet-sandbox/bullet3_bindgen.cs @@ -1915,6 +1915,8 @@ internal static unsafe partial class LibBullet3 internal static extern void b3RotateVector(double* quat, double* vec, double* vecOut); + + } [StructLayout(LayoutKind.Sequential)] diff --git a/dotnet-sandbox/libphysx_csbindgen.cs b/dotnet-sandbox/libphysx_csbindgen.cs index f4a219d..aa801a0 100644 --- a/dotnet-sandbox/libphysx_csbindgen.cs +++ b/dotnet-sandbox/libphysx_csbindgen.cs @@ -15540,6 +15540,8 @@ internal static unsafe partial class LibPhysx internal static extern PxPvdTransport* phys_PxDefaultPvdFileTransportCreate(byte* name); + + } [StructLayout(LayoutKind.Sequential)] diff --git a/dotnet-sandbox/libpng16_csbindgen.cs b/dotnet-sandbox/libpng16_csbindgen.cs index 770d77d..18548a7 100644 --- a/dotnet-sandbox/libpng16_csbindgen.cs +++ b/dotnet-sandbox/libpng16_csbindgen.cs @@ -938,6 +938,8 @@ internal static unsafe partial class LibPng16 internal static extern int png_set_option(png_struct_def* png_ptr, int option, int onoff); + + } [StructLayout(LayoutKind.Sequential)] diff --git a/dotnet-sandbox/lz4_bindgen.cs b/dotnet-sandbox/lz4_bindgen.cs index f47d496..97c7b45 100644 --- a/dotnet-sandbox/lz4_bindgen.cs +++ b/dotnet-sandbox/lz4_bindgen.cs @@ -997,6 +997,8 @@ public static unsafe partial class LibLz4 public static extern void LZ4F_resetDecompressionContext(LZ4F_dctx_s* dctx); + + } [StructLayout(LayoutKind.Sequential)] diff --git a/dotnet-sandbox/quiche_bindgen.cs b/dotnet-sandbox/quiche_bindgen.cs index 4c65323..e36fb1f 100644 --- a/dotnet-sandbox/quiche_bindgen.cs +++ b/dotnet-sandbox/quiche_bindgen.cs @@ -416,6 +416,8 @@ internal static unsafe partial class LibQuiche internal static extern void quiche_h3_conn_free(quiche_h3_conn* conn); + + } [StructLayout(LayoutKind.Sequential)] diff --git a/dotnet-sandbox/zstd_bindgen.cs b/dotnet-sandbox/zstd_bindgen.cs index b7915ba..0b9b52e 100644 --- a/dotnet-sandbox/zstd_bindgen.cs +++ b/dotnet-sandbox/zstd_bindgen.cs @@ -626,6 +626,8 @@ internal static unsafe partial class LibZstd internal static extern nuint ZSTD_sizeof_DDict(ZSTD_DDict_s* ddict); + + } [StructLayout(LayoutKind.Sequential)]