1# Using the Union Types Generated by Bindgen 2 3**NOTE**: Rust 1.19 stabilized the `union` type (see Rust issue [#32836](https://github.com/rust-lang/rust/issues/32836)). 4 5You can pass the `--rust-target` option to tell `bindgen` to target a specific version of Rust. 6By default, `bindgen` will target the latest stable Rust. 7The `--rust-target` option accepts a specific stable version (such as "1.0" or "1.19") or "nightly". 8 9**NOTE**: The `--unstable-rust` option is deprecated; use `--rust-target nightly` instead. 10 11In general, most interactions with unions (either reading or writing) are unsafe, meaning you must surround union accesses in an `unsafe {}` block. 12 13For this discussion, we will use the following C type definitions: 14 15```c 16typedef struct { 17 int32_t a; 18 int32_t b; 19} alpha_t; 20 21typedef struct { 22 uint32_t c; 23 uint16_t d; 24 uint16_t e; 25 uint8_t f; 26} beta_t; 27 28typedef union { 29 alpha_t alfa; 30 beta_t bravo; 31} greek_t; 32``` 33 34## Relevant Bindgen Options 35 36### Library 37 38* [`bindgen::Builder::rust_target()`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.rust_target) <!-- Update when live --> 39* [`bindgen::Builder::derive_default()`](https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.derive_default) 40 41### Command Line 42 43* `--rust-target` 44* `--with-derive-default` 45 46## Which union type will Bindgen generate? 47 48Bindgen can emit one of two Rust types that correspond to C unions: 49 50* Rust's `union` builtin (only available in Rust >= 1.19, including nightly) 51* Bindgen's `BindgenUnion` (available for all Rust targets) 52 53Bindgen uses the following logic to determine which Rust union type to emit: 54 55* If the Rust target is >= 1.19 (including nightly) AND each field of the union can derive `Copy`, then generate a `union` builtin. 56* Otherwise, generate a `BindgenUnion`. 57 58## Using the `union` builtin 59 60When using the `union` builtin type, there are two choices for initialization: 61 621. Zero 632. With a specific variant 64 65```rust,ignore 66mod bindings_builtin_union; 67 68fn union_builtin() { 69 // Initalize the union to zero 70 let x = bindings_builtin_union::greek_t::default(); 71 72 // If `--with-derive-default` option is not used, the following may be used 73 // to initalize the union to zero: 74 let x = unsafe { std::mem::zeroed::<bindings_builtin_union::greek_t>() }; 75 76 // Or, it is possible to initialize exactly one variant of the enum: 77 let x = bindings_builtin_union::greek_t { 78 alfa: bindings_builtin_union::alpha_t { 79 a: 1, 80 b: -1, 81 }, 82 }; 83 84 unsafe { 85 println!("{:?}", z.alfa); // alpha_t { a: 1, b: -1 } 86 println!("{:?}", z.bravo); // beta_t { c: 1, d: 65535, e: 65535, f: 127 } 87 } 88} 89``` 90 91## Using the `BindgenUnion` type 92 93If the target Rust version does not support the new `union` type or there is a field that cannot derive `Copy`, then bindgen will provide union-like access to a `struct`. 94 95Interacting with these unions is slightly different than the new `union` types. 96You must access union variants through a reference. 97 98```rust,ignore 99mod bindings; 100 101fn bindgenunion() { 102 // `default()` or `zeroed()` may still be used with Bindgen's Union types 103 let mut x = bindings::greek_t::default(); 104 105 // This will not work: 106 // let x = bindings::greek_t { 107 // alfa: bindings::alpha_t { 108 // a: 1, 109 // b: -1, 110 // }, 111 // }; 112 113 // Instead, access the field through `.as_ref()` and `.as_mut()` helpers: 114 unsafe { 115 *x.alfa.as_mut() = bindings::alpha_t { 116 a: 1, 117 b: -1, 118 }; 119 120 println!("{:?}", x.alfa.as_ref()); // alpha_t { a: 1, b: -1 } 121 println!("{:?}", x.bravo.as_ref()); // beta_t { c: 1, d: 65535, e: 65535, f: 0 } 122 } 123``` 124 125If you attempt to access a `BindgenUnion` field directly, you will see errors like this: 126 127```text 128error[E0308]: mismatched types 129 --> src/main.rs:44:15 130 | 13144 | alfa: bindings::alpha_t { 132 | _______________^ 13345 | | a: 1, 13446 | | b: -1, 13547 | | }, 136 | |_________^ expected struct `bindings::__BindgenUnionField`, found struct `bindings::alpha_t` 137 | 138 = note: expected type `bindings::__BindgenUnionField<bindings::alpha_t>` 139 found type `bindings::alpha_t` 140``` 141