diff --git a/csbindgen-tests/src/lib.rs b/csbindgen-tests/src/lib.rs index 7bd3bc0..c252b88 100644 --- a/csbindgen-tests/src/lib.rs +++ b/csbindgen-tests/src/lib.rs @@ -606,8 +606,24 @@ pub struct CallbackTable { pub foobar: extern "C" fn(i: i32) -> i32, } + pub extern "C" fn reference_type(_a: &i32, _b: &*mut i32, _c: &[u8; 16], _d: &Context) {} +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/csbindgen/src/parser.rs b/csbindgen/src/parser.rs index 5c918d1..d58847c 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 { diff --git a/dotnet-sandbox/NativeMethods.cs b/dotnet-sandbox/NativeMethods.cs index ef6c335..bd405a2 100644 --- a/dotnet-sandbox/NativeMethods.cs +++ b/dotnet-sandbox/NativeMethods.cs @@ -176,9 +176,17 @@ namespace CsBindgen [DllImport(__DllName, EntryPoint = "call_bindgen_lz4", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] public static extern void call_bindgen_lz4(); + [DllImport(__DllName, EntryPoint = "reference_type", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] public static extern void reference_type(int* _a, int** _b, void/* byte[] */* _c, Context* _d); + [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); + + } @@ -263,6 +271,11 @@ namespace CsBindgen public delegate* unmanaged[Cdecl] foobar; } + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct TreatAsEmptyStruct + { + } + [Flags] internal enum EnumFlags : uint