| // Passing structs via FFI should work regardless of whether |
| // they get passed in multiple registers, byval pointers or the stack |
| |
| #[derive(Clone, Copy, Debug, PartialEq)] |
| #[repr(C)] |
| struct Rect { |
| a: i32, |
| b: i32, |
| c: i32, |
| d: i32, |
| } |
| |
| #[derive(Clone, Copy, Debug, PartialEq)] |
| #[repr(C)] |
| struct BiggerRect { |
| s: Rect, |
| a: i32, |
| b: i32, |
| } |
| |
| #[derive(Clone, Copy, Debug, PartialEq)] |
| #[repr(C)] |
| struct FloatRect { |
| a: i32, |
| b: i32, |
| c: f64, |
| } |
| |
| #[derive(Clone, Copy, Debug, PartialEq)] |
| #[repr(C)] |
| struct Huge { |
| a: i32, |
| b: i32, |
| c: i32, |
| d: i32, |
| e: i32, |
| } |
| |
| #[derive(Clone, Copy, Debug, PartialEq)] |
| #[repr(C)] |
| struct Huge64 { |
| a: i64, |
| b: i64, |
| c: i64, |
| d: i64, |
| e: i64, |
| } |
| |
| #[derive(Clone, Copy, Debug, PartialEq)] |
| #[repr(C)] |
| struct FloatPoint { |
| x: f64, |
| y: f64, |
| } |
| |
| #[derive(Clone, Copy, Debug, PartialEq)] |
| #[repr(C)] |
| struct FloatOne { |
| x: f64, |
| } |
| |
| #[derive(Clone, Copy, Debug, PartialEq)] |
| #[repr(C)] |
| struct IntOdd { |
| a: i8, |
| b: i8, |
| c: i8, |
| } |
| |
| #[link(name = "test", kind = "static")] |
| extern "C" { |
| fn byval_rect(a: i32, b: i32, c: i32, d: i32, e: i32, s: Rect); |
| |
| fn byval_many_rect(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, s: Rect); |
| |
| fn byval_rect_floats( |
| a: f32, |
| b: f32, |
| c: f64, |
| d: f32, |
| e: f32, |
| f: f32, |
| g: f64, |
| s: Rect, |
| t: FloatRect, |
| ); |
| |
| fn byval_rect_with_float(a: i32, b: i32, c: f32, d: i32, e: i32, f: i32, s: Rect); |
| |
| fn byval_rect_with_many_huge(a: Huge, b: Huge, c: Huge, d: Huge, e: Huge, f: Huge, g: Rect); |
| |
| fn byval_rect_with_many_huge64( |
| a: Huge64, |
| b: Huge64, |
| c: Huge64, |
| d: Huge64, |
| e: Huge64, |
| f: Huge64, |
| g: Rect, |
| ); |
| |
| fn split_rect(a: i32, b: i32, s: Rect); |
| |
| fn split_rect_floats(a: f32, b: f32, s: FloatRect); |
| |
| fn split_rect_with_floats(a: i32, b: i32, c: f32, d: i32, e: f32, f: i32, s: Rect); |
| |
| fn split_and_byval_rect(a: i32, b: i32, c: i32, s: Rect, t: Rect); |
| |
| fn split_ret_byval_struct(a: i32, b: i32, s: Rect) -> Rect; |
| |
| fn sret_byval_struct(a: i32, b: i32, c: i32, d: i32, s: Rect) -> BiggerRect; |
| |
| fn sret_split_struct(a: i32, b: i32, s: Rect) -> BiggerRect; |
| |
| fn huge_struct(s: Huge) -> Huge; |
| |
| fn huge64_struct(s: Huge64) -> Huge64; |
| |
| fn float_point(p: FloatPoint) -> FloatPoint; |
| |
| fn float_one(f: FloatOne) -> FloatOne; |
| |
| fn int_odd(i: IntOdd) -> IntOdd; |
| } |
| |
| fn main() { |
| let s = Rect { a: 553, b: 554, c: 555, d: 556 }; |
| let t = BiggerRect { s: s, a: 27834, b: 7657 }; |
| let u = FloatRect { a: 3489, b: 3490, c: 8. }; |
| let v = Huge { a: 5647, b: 5648, c: 5649, d: 5650, e: 5651 }; |
| let w = Huge64 { a: 1234, b: 1335, c: 1436, d: 1537, e: 1638 }; |
| let p = FloatPoint { x: 5., y: -3. }; |
| let f1 = FloatOne { x: 7. }; |
| let i = IntOdd { a: 1, b: 2, c: 3 }; |
| |
| unsafe { |
| byval_rect(1, 2, 3, 4, 5, s); |
| byval_many_rect(1, 2, 3, 4, 5, 6, s); |
| byval_rect_floats(1., 2., 3., 4., 5., 6., 7., s, u); |
| byval_rect_with_float(1, 2, 3.0, 4, 5, 6, s); |
| byval_rect_with_many_huge(v, v, v, v, v, v, Rect { a: 123, b: 456, c: 789, d: 420 }); |
| byval_rect_with_many_huge64(w, w, w, w, w, w, Rect { a: 1234, b: 4567, c: 7890, d: 4209 }); |
| split_rect(1, 2, s); |
| split_rect_floats(1., 2., u); |
| split_rect_with_floats(1, 2, 3.0, 4, 5.0, 6, s); |
| split_and_byval_rect(1, 2, 3, s, s); |
| split_rect(1, 2, s); |
| assert_eq!(huge_struct(v), v); |
| assert_eq!(huge64_struct(w), w); |
| assert_eq!(split_ret_byval_struct(1, 2, s), s); |
| assert_eq!(sret_byval_struct(1, 2, 3, 4, s), t); |
| assert_eq!(sret_split_struct(1, 2, s), t); |
| assert_eq!(float_point(p), p); |
| assert_eq!(int_odd(i), i); |
| |
| // MSVC/GCC/Clang are not consistent in the ABI of single-float aggregates. |
| // x86_64: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82028 |
| // i686: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82041 |
| #[cfg(not(all(windows, target_env = "gnu")))] |
| assert_eq!(float_one(f1), f1); |
| } |
| } |