試験勉強中についつい部屋の掃除を始めてしまうとか、いわゆる現実逃避ですね。今回はそんな感じのものです。Rustは勉強中なので全然違う話ではないのですが、興味本位というのは否定できません。
Rustでビューアを作る
こんにちは。お試しで作ったものの結局使われることが無かったもの供養シリーズです。
今回はRustで、GUIで、FA用カメラとしては有名なBaslerのビューアを作ってみました。RustでGUIというだけでも挑戦的なんじゃないかと思いますが、Dear ImGuiを気に入って使っているのでその系統のeguiを使っています。
完成したものはGitHubにあります。ご参考まで。
準備
Rust と egui の準備は特に問題ないかと思います。
BaslerはpylonというSDKがあるので、Cなどからは容易に利用することが可能です。Rustだとどうするのかなぁと思って探したら、ラッパーがありました。pylon-cxxを使います。
その他いろいろ追加する必要がありますが、最終形状は以下になっています。
[dependencies]
anyhow = "1"
eframe = {features = [
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
]}
#egui_extras = {"0.22.0" , features = ["image"]}
env_logger = "0.10"
itertools = "0.11.0"
log = "0.4.19"
pylon-cxx = "0.3.4"
eguiを利用するだけだったら、もっとシンプルに用意できたかもしれませんが、そこまでやっていません。
難所
カメラのインスタンスを構造体に収めたいと思ったので pylon-cxxとはちょっと違う感じになったのですが、ここが苦労の始まりでした。
構造体を初期化するときに、オブジェクトとその参照の両方を必要としていて、コンパイラが許してくれません。Rustではどうするの?みたいな質問も見ます。結局こちらを参照しました。
根本的な解決策にはなっていませんが、unsafe
を使います。
let pylon = pylon_cxx::Pylon::new();
let lefp: &'cam _ = unsafe { &*(&pylon as *const _) };
let camera = pylon_cxx::TlFactory::instance(lefp)
.create_first_device()
.unwrap();
Self { camera, pylon }
そういう訳なので、この構造体を削除する時も注意が必要なようで、なんとなく消える順番に書くのがよさそうです。
struct GrabApp<'cam> {
// メモリを開放して欲しい順?にフィールドを記述
camera: InstantCamera<'cam>,
#[allow(dead_code)]
pylon: Pylon,
}
その他、日本語表示のいろいろも加えてあります。
動かし方
pylon SDKにはエミュレータが内蔵されており、本物のカメラが無くてもお試しができます。環境変数を設定してください。数字はエミュレータの個数です。1個でも大丈夫です。
PYLON_CAMEMU=2
エミュレータは白黒なので、これ前提のコードになっています。表示はRGBのカラー表示なので、バッファの順番を間違えなければ、カラーでも表示できると思います。
おわりに
C++ で ImGui を使ったビューアはここまで苦労しませんでした。でも、個人的にはRust使えて、GUIもなんとかなったので、満足です。