Skip to content

Commit 9deaf5c

Browse files
committed
Added latest changes.
1 parent 00e431b commit 9deaf5c

File tree

1 file changed

+22
-134
lines changed

1 file changed

+22
-134
lines changed

book/src/using-bitfields.md

Lines changed: 22 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
# Using the Bitfield Types Generated by Bindgen
22

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+
312
For this discussion, we will use the following C type definitions and functions.
413
```c
514
typedef struct {
615
unsigned int a: 1;
716
unsigned int b: 1;
817
unsigned int c: 2;
918

10-
} bitfield;
19+
} StructWithBitfields;
1120

1221
// Create a default bitfield
13-
bitfield create_bitfield();
22+
StructWithBitfields create_bitfield();
1423

1524
// Print a bitfield
16-
void print_bitfield(bitfield bfield)
25+
void print_bitfield(StructWithBitfields bfield);
1726
```
1827
1928
Bindgen creates a set of field getters and setters for interacting with the bitset. For example,
@@ -36,7 +45,7 @@ will print out
3645
a set to 1
3746
b set to 1
3847
c set to 3
39-
bitfield: a:1, b:1, c:3
48+
StructWithBitfields: a:1, b:1, c:3
4049
```
4150

4251
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
5463

5564
```text
5665
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
7367
```
7468

75-
## Unsigned bitfield gotcha
69+
To create a new bitfield in Rust, use the bitfield allocation unit constructor.
7670

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.
11272

11373
```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) };
13478
```
13579

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
18581

18682
```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
19684
```

0 commit comments

Comments
 (0)