bindgenを使ってみた。
Linuxのinput event
input event はキーボードやマウス、タッチスクリーンなどのイベントです。
このページがわかりやすい。
Linux Input Subsystemの使い方
このページの最初のサンプルの「音量調整プログラム」と似たものをRustで書いてみました。
bindgen
bindgenはCのヘッダファイルを読んで、そのストラクチャや定数、関数の宣言をRustの形式に変換してくれます。
bindgen users guide
bindgenの準備
sudo apt install clang
cargo install bindgen
ヘッダファイルを変換する
bindgen users guide のチュートリアルでは、build.rsを作ってcargoでビルドするときにヘッダファイルの変換をするようにしていますが、ここでは手っ取り早くbindgen
コマンドを手で実行してみます。
$ bindgen /usr/include/linux/input.h -o src/input.rs
Custom { kind: Other, error: StringError("Internal rustfmt error") }
むむ、何かエラーになった。
でもファイルはできているようなので深入りせずにこのまま進みます。(rustc は1.29.1 を使用)
サンプルプログラム
gistに貼りました。ここ
デバイスファイルからストラクチャのサイズ分を読んで、キャストする部分は以下の通り。
fn read_input_event(f: &mut File) -> io::Result<(input_event)> {
const sz: usize = std::mem::size_of::<input_event>();
let mut buf = [0; sz];
f.read_exact(&mut buf)?;
let ie: input_event = unsafe { std::mem::transmute(buf) };
Ok(ie)
}
つまずいたところ
最初にclangをインストールするのを忘れていた。bindgen
は実行できるけど、stddef.h
が見つからないという不思議な挙動になった。
input_event
のストラクチャにはtype
という名のメンバがあった。これはRustの予約語と重なるので、変換して出力されたファイルでは type_
に変更されていた。
定数のdefine値は全てu32
として生成される。ストラクチャのメンバがu16
で、Rustは型に厳しいので明示的なキャストが必要だった。