1
1
# Using the Bitfield Types Generated by Bindgen
2
2
3
+ ## Bitfield Strategy Overview
4
+
5
+ As Rust does not support bitfields, Bindgen generates an opaque struct for each with the following characteristics
6
+ * Immutable getter functions for each bitfield named ``` <bitfield> ```
7
+ * Setter functions for each bitfield named ``` set_<bitfield> ```
8
+ * A static constructor ``` new_bitfield_{1, 2, ...} ``` with a parameter for each bitfield contained within the opaque physical field.
9
+
10
+ ## Bitfield examples
11
+
3
12
For this discussion, we will use the following C type definitions and functions.
4
13
``` c
5
14
typedef struct {
6
15
unsigned int a: 1;
7
16
unsigned int b: 1;
8
17
unsigned int c: 2;
9
18
10
- } bitfield ;
19
+ } StructWithBitfields ;
11
20
12
21
// Create a default bitfield
13
- bitfield create_bitfield ();
22
+ StructWithBitfields create_bitfield ();
14
23
15
24
// Print a bitfield
16
- void print_bitfield (bitfield bfield)
25
+ void print_bitfield (StructWithBitfields bfield);
17
26
```
18
27
19
28
Bindgen creates a set of field getters and setters for interacting with the bitset. For example,
@@ -36,7 +45,7 @@ will print out
36
45
a set to 1
37
46
b set to 1
38
47
c set to 3
39
- bitfield : a:1, b:1, c:3
48
+ StructWithBitfields : a:1, b:1, c:3
40
49
```
41
50
42
51
Overflowing a bitfield will result in the same behavior as in C/C++: the bitfield will be set to 0.
@@ -54,143 +63,22 @@ will print out
54
63
55
64
``` text
56
65
c set to 0 due to overflow
57
- bitfield: a:1, b:1, c:0
58
- ```
59
-
60
- To create a new bitfield in Rust, use mem::zeroed.
61
-
62
- ``` rust,ignore
63
- let mut bfield = unsafe { mem::zeroed::<bitfield>() };
64
- bfield.set_a(1);
65
- bfield.set_c(2);
66
- unsafe { print_bitfield(bfield) };
67
- ```
68
-
69
- This will print out
70
-
71
- ``` text
72
- bitfield: a:1, b:0, c:2
66
+ StructWithBitfields: a:1, b:1, c:0
73
67
```
74
68
75
- ## Unsigned bitfield gotcha
69
+ To create a new bitfield in Rust, use the bitfield allocation unit constructor.
76
70
77
- Special care should be given to handling unsigned bitfields. Let's change 'c' field to an int. C's valid values are now -2, -1, 0, and 1.
78
-
79
- ``` c
80
- typedef struct {
81
- unsigned int a: 1;
82
- unsigned int b: 1;
83
- int c: 2;
84
-
85
- } bitfield;
86
- ```
87
-
88
- Let's now walk the bitfield possibilities in both C and Rust up to the first overflow on each end:
89
-
90
- ``` c
91
- void walk_bitfield () {
92
- bitfield bfield = create_bitfield();
93
- print_bitfield (bfield);
94
- bfield.c = 1;
95
- print_bitfield(bfield);
96
- bfield.c = 2;
97
- print_bitfield(bfield);
98
- bfield.c = 3;
99
- print_bitfield(bfield);
100
- bfield.c = 4;
101
- print_bitfield(bfield);
102
- bfield.c = -1;
103
- print_bitfield(bfield);
104
- bfield.c = -2;
105
- print_bitfield(bfield);
106
- bfield.c = -3;
107
- print_bitfield(bfield);
108
- bfield.c = -4;
109
- print_bitfield(bfield);
110
- }
111
- ```
71
+ Note: This requires the Builder's derive_default to be set to true, otherwise the necessary Default functions won't be generated.
112
72
113
73
``` rust,ignore
114
- fn walk_bitfield() {
115
- let mut bfield = unsafe { mem::zeroed::<bitfield>() };
116
- unsafe { print_bitfield(bfield) };
117
- bfield.set_c(1);
118
- unsafe { print_bitfield(bfield) };
119
- bfield.set_c(2);
120
- unsafe { print_bitfield(bfield) };
121
- bfield.set_c(3);
122
- unsafe { print_bitfield(bfield) };
123
- bfield.set_c(4);
124
- unsafe { print_bitfield(bfield) };
125
- bfield.set_c(-1);
126
- unsafe { print_bitfield(bfield) };
127
- bfield.set_c(-2);
128
- unsafe { print_bitfield(bfield) };
129
- bfield.set_c(-3);
130
- unsafe { print_bitfield(bfield) };
131
- bfield.set_c(-4);
132
- unsafe { print_bitfield(bfield) };
133
- }
74
+ let bfield = StructWithBitfields{
75
+ _bitfield_1: StructWithBitfields::new_bitfield_1(0,0,0),
76
+ ..Default::default()
77
+ }; unsafe { print_bitfield(bfield) };
134
78
```
135
79
136
- This produces identical results in C's print function:
137
-
138
- ``` text
139
- Print C walk
140
- bitfield: a:0, b:0, c:0
141
- bitfield: a:0, b:0, c:1
142
- bitfield: a:0, b:0, c:-2
143
- bitfield: a:0, b:0, c:-1
144
- bitfield: a:0, b:0, c:0
145
- bitfield: a:0, b:0, c:-1
146
- bitfield: a:0, b:0, c:-2
147
- bitfield: a:0, b:0, c:1
148
- bitfield: a:0, b:0, c:0
149
- Print Rust walk
150
- bitfield: a:0, b:0, c:0
151
- bitfield: a:0, b:0, c:1
152
- bitfield: a:0, b:0, c:-2
153
- bitfield: a:0, b:0, c:-1
154
- bitfield: a:0, b:0, c:0
155
- bitfield: a:0, b:0, c:-1
156
- bitfield: a:0, b:0, c:-2
157
- bitfield: a:0, b:0, c:1
158
- bitfield: a:0, b:0, c:0
159
- ```
160
-
161
- However, Bindgen's getter provides different results:
162
-
163
- ``` rust,ignore
164
- fn getter_walk_bitfield() {
165
- let mut bfield = unsafe { mem::zeroed::<bitfield>() };
166
- println!("c set to {}", bfield.c());
167
- bfield.set_c(1);
168
- println!("c set to {}", bfield.c());
169
- bfield.set_c(2);
170
- println!("c set to {}", bfield.c());
171
- bfield.set_c(3);
172
- println!("c set to {}", bfield.c());
173
- bfield.set_c(4);
174
- println!("c set to {}", bfield.c());
175
- bfield.set_c(-1);
176
- println!("c set to {}", bfield.c());
177
- bfield.set_c(-2);
178
- println!("c set to {}", bfield.c());
179
- bfield.set_c(-3);
180
- println!("c set to {}", bfield.c());
181
- bfield.set_c(-4);
182
- println!("c set to {}", bfield.c());
183
- }
184
- ```
80
+ This will print out
185
81
186
82
``` text
187
- c set to 0
188
- c set to 1
189
- c set to 2
190
- c set to 3
191
- c set to 0
192
- c set to 3
193
- c set to 2
194
- c set to 1
195
- c set to 0
83
+ StructWithBitfields: a:1, b:0, c:2
196
84
```
0 commit comments