I have problem with resolving c-union structure XEvent.
I'm experimenting with Xlib and X Record Extension in Rust. I'm generate ffi-bindings with rust-bindgen. All code hosted on github alxkolm/rust-xlib-record.
Trouble happen on line src/main.rs:106 when I try extract data from XEvent structure.
let key_event: *mut xlib::XKeyEvent = event.xkey(); println!("KeyPress {}", (*key_event).keycode); // this always print 128 on any key
My program listen key events and print out keycode
. But it is always 128 on any key I press. I think this wrong conversion from C union type to Rust type.
Definition of XEvent starts here src/xlib.rs:1143. It's the c-union. Original C definition here.
Code from GitHub can be run by cargo run
command. It's compile without errors.
What I do wrong?
Beware that rustbindgen
generates binding to C union
with as much safety as in C; as a result, when calling:
event.xkey(); // gets the C union 'xkey' field
There is no runtime check that xkey
is the field currently containing a value.
This is because since C does not have tagged union
(ie, the union
knowing which field is currently in use), developers came up with various ways of encoding this information (*), the two that I know of being:
union
union
Here, you are in the latter case int type;
is the first field of the union and each nested structure starts with int _type;
to denote this. As a result, you need a two-steps approach:
type()
The mapping from the value of type to the actual field being used should be part of the documentation of the C library, hopefully.
I invite you to come up with a wrapper around this low-level union
that will make it safer to retrieve the result. At the very least, you could check it is the right type in the accessor; the full approach being to come up with a Rust enum
that would wrap proxies to all the fields and allow pattern-matching.
(*) and actually sometimes disregard it altogether, for example in C99 to reinterpret a float
as an int
a union { float f; int i; }
can be used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With