summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Barnard <eabarnard@gmail.com>2014-12-29 21:40:49 +0100
committerEdward Barnard <eabarnard@gmail.com>2014-12-29 21:40:49 +0100
commit6935ccb534c288a305f873d6b38bda646876b63d (patch)
tree3a1f20a6369f4e81f16a2d5847ff1abdd4434a19
parent87c3a33f405d65af2d06194c6c7b50e781391d5e (diff)
Support more composite field types.
-rw-r--r--src/parser.rs39
-rw-r--r--tests/headers/struct_with_anon_struct_array.h6
-rw-r--r--tests/headers/struct_with_anon_struct_pointer.h6
-rw-r--r--tests/struct.rs33
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] } };