diff options
author | Edward Barnard <eabarnard@gmail.com> | 2014-12-29 21:40:49 +0100 |
---|---|---|
committer | Edward Barnard <eabarnard@gmail.com> | 2014-12-29 21:40:49 +0100 |
commit | 6935ccb534c288a305f873d6b38bda646876b63d (patch) | |
tree | 3a1f20a6369f4e81f16a2d5847ff1abdd4434a19 | |
parent | 87c3a33f405d65af2d06194c6c7b50e781391d5e (diff) |
Support more composite field types.
-rw-r--r-- | src/parser.rs | 39 | ||||
-rw-r--r-- | tests/headers/struct_with_anon_struct_array.h | 6 | ||||
-rw-r--r-- | tests/headers/struct_with_anon_struct_pointer.h | 6 | ||||
-rw-r--r-- | tests/struct.rs | 33 |
4 files changed, 74 insertions, 10 deletions
diff --git a/src/parser.rs b/src/parser.rs index 607d0bc3..602641e7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -304,8 +304,9 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, } // The Clang C api does not fully expose composite fields, but it - // does expose them in a way that can be detected. When the current - // field kind is CXType_Unexposed and the previous member is a + // does expose them in a way that can be detected. When the current + // field kind is CXType_Unexposed, CXType_Pointer or + // CXType_ConstantArray and the previous member is a // composite type--the same type as this field-- then this is a // composite field. e.g.: // @@ -315,15 +316,33 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, // char b; // } bar; // }; - let is_composite = if cursor.cur_type().kind() == CXType_Unexposed { - if let TComp(ref ty_compinfo) = ty { - match members.last() { - Some(&CompMember::Comp(ref c)) => c.borrow().deref() as *const _ == ty_compinfo.borrow().deref() as *const _, - _ => false + // + // struct foo { + // union { + // int a; + // char b; + // } *bar; + // }; + // + // struct foo { + // union { + // int a; + // char b; + // } bar[3]; + // }; + // + let is_composite = match (cursor.cur_type().kind(), &ty) { + (CXType_Unexposed, &TComp(ref ty_compinfo)) | + (CXType_Pointer, &TPtr(box TComp(ref ty_compinfo), _, _)) | + (CXType_ConstantArray, &TArray(box TComp(ref ty_compinfo), _, _)) => { + if let Some(&CompMember::Comp(ref c)) = members.last() { + c.borrow().deref() as *const _ == ty_compinfo.borrow().deref() as *const _ + } else { + false } - } else { false } - } else { false }; - + }, + _ => false + }; let field = FieldInfo::new(name, ty.clone(), bit); if is_composite { diff --git a/tests/headers/struct_with_anon_struct_array.h b/tests/headers/struct_with_anon_struct_array.h new file mode 100644 index 00000000..2d9d7bdd --- /dev/null +++ b/tests/headers/struct_with_anon_struct_array.h @@ -0,0 +1,6 @@ +struct foo { + struct { + int a; + int b; + } bar[2]; +}; diff --git a/tests/headers/struct_with_anon_struct_pointer.h b/tests/headers/struct_with_anon_struct_pointer.h new file mode 100644 index 00000000..0c486d84 --- /dev/null +++ b/tests/headers/struct_with_anon_struct_pointer.h @@ -0,0 +1,6 @@ +struct foo { + struct { + int a; + int b; + } *bar; +}; diff --git a/tests/struct.rs b/tests/struct.rs index 980ea558..f9900349 100644 --- a/tests/struct.rs +++ b/tests/struct.rs @@ -18,6 +18,39 @@ fn test_struct_with_anon_struct() { } #[test] +fn test_struct_with_anon_struct_array() { + mod ffi { bindgen!("headers/struct_with_anon_struct_array.h"); } + let mut x = ffi::Struct_foo { bar: [ + ffi::Struct_Unnamed1 { a: 0, b: 0 }, + ffi::Struct_Unnamed1 { a: 1, b: 1 } ] + }; + + x.bar[1].a = 1; + x.bar[1].b = 2; + + assert_eq!(x.bar[1].a, 1); + assert_eq!(x.bar[1].b, 2); +} + +#[test] +fn test_struct_with_anon_struct_pointer() { + mod ffi { bindgen!("headers/struct_with_anon_struct_pointer.h"); } + let mut unnamed = box ffi::Struct_Unnamed1 { a: 0, b: 0 }; + + unsafe { + let mut x = ffi::Struct_foo { bar: ::std::mem::transmute(unnamed) }; + + (*x.bar).a = 1; + (*x.bar).b = 2; + + assert_eq!((*x.bar).a, 1); + assert_eq!((*x.bar).b, 2); + + ::std::ptr::read(x.bar); + } +} + +#[test] fn test_struct_with_anon_union() { mod ffi { bindgen!("headers/struct_with_anon_union.h"); } let mut x = ffi::Struct_foo { bar: ffi::Union_Unnamed1 { _bindgen_data_: [0] } }; |