はじめに

Windows向けに「小さくて依存の少ない単体実行型のGUIアプリケーション」を作る場合、C++/MFC は長年定番の選択肢でした。 では、同じような軽量性を維持しつつ、より安全でモダンな言語である Rust で同様のアプリを作ることはできるのでしょうか? 本記事では、Rust のGUI開発事情を俯瞰しつつ、現実的にフットプリントの小さなGUIアプリをRustで作れるかどうか、Slint を用いた実測比較を通して検証していきます。

■ RustでWindowsネイティブGUIはまだ現実的ではない

以前の記事の繰り返しになりますが、最初に確認しておくべきは、2025年現在、Rustで Windows ネイティブ(Win32 / MFC / WPF に相当)GUI を実用レベルで構築するのは難しいという点です。 理由としては次のとおりです。
  • MicrosoftがRust向けGUIフレームワークを公式サポートしていない
  • Win32 / WinRT / WinUI まわりのRust bindingsは断片的で、包括的ではない
  • community製の native-windows-gui などは機能面・保守面で不安がある
  • GUIデザイナが存在しない
  • WPF / MFC のような成熟したエコシステムを期待できない
Windows専用GUI をRustで作るのであれば、現時点ではC++やC#に軍配が上がります。

■ Rust はマルチプラットフォームGUIなら得意

Rustの強みは、マルチプラットフォームで安全なGUIアプリを比較的小さなフットプリントで構築できる点にあります。主要な選択肢を整理すると以下のとおりです。
フレームワーク 特徴
Tauri WebViewベース。UIをHTML/CSS/JSで制作。軽いがWebView依存。
Iced Rustの宣言的UI。機能豊富だがサイズは中程度。
Dioxus Desktop Reactライク。WebViewベースで中程度のフットプリント。
Flutter+Rust bindings 重量級。バイナリが大きい。
Slint ネイティブ描画で軽量。UI言語がQt/QMLライク。組込みにも対応。
WebViewというのはアプリ中でブラウザを動かす技術ですので、高機能なGUIを実現できますが、それなりに大きくなります。したがって、この中から「軽量さ」で選ぶのであれば Slint が最適候補 となります。

■ Slint を選ぶ理由:軽量・高速・依存が少ない

Slint は、組込み用途・省リソース環境も視野に入れた軽量GUIフレームワークであり、次の特徴を備えています。
  • QMLライクな画面定義言語による宣言的UI
  • Rust / C++ / JavaScript など複数言語バインディング
  • OSとCランタイム以外に依存しないスタティックリンク構成が可能
  • ネイティブレンダリング(WebView不要)
  • 1つのソースで Windows / macOS / Linux に対応
  • Android / iOS / WebAssembly / 組込み(ARM Cortex-Mなど)にも対応
軽量 × マルチプラットフォーム × Rustの安全性」の三拍子が揃っている点が、他のフレームワークにはない特徴です。

■ Slint はどんなプラットフォームで動くのか

Slint のサポート範囲は広く、GUIフレームワークとしては異例の柔軟性があります。

● デスクトップ(完全対応)

OS 備考
Windows Direct2D / Skia / ソフトウェア描画
Linux X11 / Wayland、OpenGL / ソフトウェア描画
macOS CoreGraphics / AppKit
Rustで「3OS共通のネイティブGUI」を作れる点は大きな魅力です。

● モバイル(Android / iOS)

OS 状況
Android 動作実績あり(cargo-ndk)
iOS Xcode toolchain + Rust でビルド可能
Flutterほど巨大にならず、TauriのようにWebViewを必要としない、 Rustネイティブでモバイルアプリが作れるという非常にユニークな立ち位置です。

● WebAssembly(WASM)

Slintは WebAssembly にも対応しており、ブラウザ上で動くGUIをRustだけで構築できます。
  • WebGLレンダリング
  • バンドルサイズも比較的軽量
  • .slint ファイルはそのままで動作
C++/MFCでは絶対にできない領域です。

● 組み込み・家電・産業機器系

Slintは Qt/QML の軽量版のような位置づけであり、組み込み向けに非常に強いのが特徴です。
  • ARM Cortex-M クラスでの動作
  • Raspberry Pi / i.MX などで実績多数
  • GPUなしで動くソフトウェアレンダリング
  • 数百KB〜数MB級で運用可能
この分野でも Rust + Slint は現実的で、今後さらに普及が見込まれます。

■ Slint の開発しやすさ

Rust + Slint の強みの1つが 開発体験の良さ です。

● MFC の辛さ

  • .rc リソースの座標をいじる地獄
  • DPI対応を自前でやる必要
  • ロジックとUIが混在しがち
  • メモリ管理の負担
  • C++ビルドの遅さ(静的リンク構成では特に遅い)
特に「ちょっとしたダイアログを作るだけでも面倒」という経験のある方は多いはずです。

● Slint の UI 言語は現代的で簡潔

UIは .slint ファイルに宣言的に書きます。
Text {
    text: "Hello, Slint!";
    horizontal-alignment: center;
}
読みやすく、レイアウトもQMLライクで柔軟。 Rust側は以下のようにシンプルです。
let app = AppWindow::new().unwrap();
app.run();
所有権やメモリ管理はRustが安全に行うため、UIコードでポインタ管理に悩まされることはありません。

● Slint Designer(GUIエディタ)が使える

SlintはGUIデザイナを提供しており:
  • ドラッグ&ドロップでUI配置
  • DPI変更を即プレビュー
  • ダークモード切り替え
  • プロパティ編集
  • .slint ファイルへ即反映
MFCのように「座標とサイズをいじって何度もコンパイルし直す」必要は一切ありません。

■ Slint の最小アプリを作ってサイズを測る

最小構成のアプリとして、テキスト文字列とボタンだけのアプリを作ってみます。

📁 Cargo.toml

Slintはバージョン1.14を使用しました。
[package]
name = "SmallGui"
version = "0.1.0"
edition = "2021"
build = "build.rs"

[dependencies]
slint = "1.14"

[build-dependencies]
slint-build = "1.14"

📁 ui/main.slint

画面定義言語です。QMLライクな文法なのでQtの開発経験がある方には取っつきやすいのではないでしょうか。
import { Button } from "std-widgets.slint";

export component AppWindow inherits Window {
    width: 200px;
    height: 120px;

    // OK ボタン押下イベントを通知するコールバック
    callback ok_clicked;

    VerticalLayout {
        padding: 8px;
        spacing: 8px;

        Text {
            text: "Hello, World!";
            horizontal-alignment: center;
        }
    }

    // 右下の OK ボタン(レイアウト外で絶対配置)
    Button {
        text: "OK";

        x: parent.width - self.width - 8px;
        y: parent.height - self.height - 8px;

        clicked => { root.ok_clicked(); }
    }
}

📁 src/main.rs

Rustのソースコードです。
slint::include_modules!();

fn main() {
    let app = AppWindow::new().unwrap();

    // 弱参照を取っておく
    let app_weak = app.as_weak();
    // ボタンが押されたらイベントループを終了させる
    app.on_ok_clicked(move || {
        if let Some(_app) = app_weak.upgrade() {
            let _ = slint::quit_event_loop();
        }
    });

    let _ = app.run();
}

📁 build.rs

ビルド時に実行されるコードです。
fn main() {
    slint_build::compile("ui/main.slint").unwrap();
}
これらをcargo build --release でビルドすると、スタティックリンクで実行ファイルが生成されます。そのサイズは**6,129 KB(約 6MB)**となりました。 実行するとこのような画面が表示されます。 image-20251126215743171

■ Slint vs MFC の実行ファイルサイズ比較

ソースコードは省略しますが、比較対象としてVisual Studio の「MFC アプリケーション(スタティックリンク)」でダイアログベースのアプリを作り、ラベルとボタンだけを配置したアプリをビルドしました。
項目 実行サイズ(Release)
Slint 最小アプリ(Rust) 6,129 KB
MFC 最小アプリ(C++, Static) 3,888 KB
MFC のほうが 約 2MB 小さい という結果になりました。

■ 結果をどう読むか?

● MFCのサイズはやはり小さい

MFCは静的リンク構成でもかなり小さな実行ファイルができます。MFCではGUIの描画をUSER32.dll, GDI32.dllなどのOSのシステムDLLが行っていますので、自力で描画しているSlintは圧倒的に不利です。逆にSlintは自力で描画しているのにこのサイズだというのは驚異的であるとも言えます。

● Rust + Slint は Rust GUI としては非常に小さい

同様のことを Tauri や WebViewベースでやると、20〜50MB は優に超えるため、Slint の 6MB は十分に軽い 領域です。

● マルチプラットフォーム性では Slint の圧勝

MFCはWindowsのみですが、Slintは:
  • Windows
  • Linux
  • macOS
  • Android
  • iOS
  • WebAssembly
  • 組み込み …すべて同じUI言語で開発できます。

● 開発のしやすさも Slint の圧勝

  • 宣言的UI
  • Designerあり
  • Rustの安全性
  • 依存が少なく配布しやすい
MFCを使う動機は「サイズ」以外ほぼ残っていないのが現状です。

■ 結論:Rust + Slint は “現代的・軽量・安全” なGUIアプリ開発の有力候補

今回の検証をまとめると以下のとおりです。
  1. Windows専用でサイズ最優先なら MFC が依然として最小
  2. Rustで軽量GUIを作るなら Slint が現状最有力
  3. Slintは Rust GUI の中でも圧倒的に軽量で依存が少ない
  4. 開発のしやすさはMFCとは比較にならないほど良い
  5. マルチプラットフォーム対応は Slint の大きな強み
  6. WebAssembly・組み込みまでカバーするGUIは他にほぼ存在しない
「C++の代替として軽量GUIをRustで作る」というテーマに対して、Slint は十分に実用的であり、かつ将来性の高い選択と言えます。