From dd6330a57361bac38e4a4e7743852955add22128 Mon Sep 17 00:00:00 2001 From: yamachu Date: Wed, 6 Sep 2023 19:30:21 +0900 Subject: [PATCH 1/2] treat and parse structs without repr attributes as unit structs --- csbindgen/src/parser.rs | 53 ++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/csbindgen/src/parser.rs b/csbindgen/src/parser.rs index bdfba17..8928798 100644 --- a/csbindgen/src/parser.rs +++ b/csbindgen/src/parser.rs @@ -170,23 +170,42 @@ pub fn collect_struct(ast: &syn::File, result: &mut Vec) { is_union: true, }); } else if let Item::Struct(t) = item { - if let syn::Fields::Named(f) = &t.fields { - let struct_name = t.ident.to_string(); - let fields = collect_fields(f); - result.push(RustStruct { - struct_name, - fields, - is_union: false, - }); - } else if let syn::Fields::Unnamed(f) = &t.fields { - let struct_name = t.ident.to_string(); - let fields = collect_fields_unnamed(f); - result.push(RustStruct { - struct_name, - fields, - is_union: false, - }); - } else if let syn::Fields::Unit = &t.fields { + let mut repr = None; + for attr in &t.attrs { + let last_segment = attr.path.segments.last().unwrap(); + if last_segment.ident == "repr" { + repr = Some(attr.tokens.to_string()); + } + } + + if let Some(_) = repr { + if let syn::Fields::Named(f) = &t.fields { + let struct_name = t.ident.to_string(); + let fields = collect_fields(f); + result.push(RustStruct { + struct_name, + fields, + is_union: false, + }); + } else if let syn::Fields::Unnamed(f) = &t.fields { + let struct_name = t.ident.to_string(); + let fields = collect_fields_unnamed(f); + result.push(RustStruct { + struct_name, + fields, + is_union: false, + }); + } else if let syn::Fields::Unit = &t.fields { + let struct_name = t.ident.to_string(); + let fields: Vec = Vec::new(); + result.push(RustStruct { + struct_name, + fields, + is_union: false, + }); + } + } else { + // non #[repr(?)] struct, treat as Unit struct let struct_name = t.ident.to_string(); let fields: Vec = Vec::new(); result.push(RustStruct { From c27e01bd905352d3973fd47635ef73917866e15c Mon Sep 17 00:00:00 2001 From: yamachu Date: Wed, 6 Sep 2023 19:35:34 +0900 Subject: [PATCH 2/2] Add sample case --- csbindgen-tests/src/lib.rs | 14 ++++++++++++++ dotnet-sandbox/NativeMethods.cs | 11 +++++++++++ 2 files changed, 25 insertions(+) diff --git a/csbindgen-tests/src/lib.rs b/csbindgen-tests/src/lib.rs index 4983013..0b91338 100644 --- a/csbindgen-tests/src/lib.rs +++ b/csbindgen-tests/src/lib.rs @@ -606,6 +606,20 @@ pub struct CallbackTable { pub foobar: extern "C" fn(i: i32) -> i32, } +pub struct InternalHiddenContext { + pub a: i32 +} + +pub struct TreatAsEmptyStruct { + internal: std::sync::Arc +} + +#[no_mangle] +pub unsafe extern "C" fn init_treat_as_empty_struct_context(_out: NonNull>) {} + +#[no_mangle] +pub unsafe extern "C" fn free_treat_as_empty_struct_context(_src: *mut TreatAsEmptyStruct) {} + // fn run_physix(){ // unsafe { // let foundation = physx_create_foundation(); diff --git a/dotnet-sandbox/NativeMethods.cs b/dotnet-sandbox/NativeMethods.cs index 01e7a4b..0003c51 100644 --- a/dotnet-sandbox/NativeMethods.cs +++ b/dotnet-sandbox/NativeMethods.cs @@ -176,6 +176,12 @@ namespace CsBindgen [DllImport(__DllName, EntryPoint = "call_bindgen_lz4", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] public static extern void call_bindgen_lz4(); + [DllImport(__DllName, EntryPoint = "init_treat_as_empty_struct_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void init_treat_as_empty_struct_context(TreatAsEmptyStruct** _out); + + [DllImport(__DllName, EntryPoint = "free_treat_as_empty_struct_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void free_treat_as_empty_struct_context(TreatAsEmptyStruct* _src); + } @@ -260,6 +266,11 @@ namespace CsBindgen public delegate* unmanaged[Cdecl] foobar; } + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct TreatAsEmptyStruct + { + } + [Flags] internal enum EnumFlags : uint