MFCプログラマが見るTauri + Rust:MACアドレス取得で理解する構造比較
目次
5 min read
はじめに
長年MFCでWindowsアプリを作ってきた視点から見ると、Tauri + Rust構成は「新しいようで、やっていることはかなり似ている」と感じる。
ただし違いは明確で、
UIとロジックが言語レベルで分離されている点が最大のポイントになる。
この記事では「MACアドレス取得ツール」を題材に、
- MFC版
- Tauri + Rust版
- Rust関数の読み方
をまとめて理解できる形に整理する。
作るもの
シンプルなツール:
- ボタンを押す
- MACアドレス一覧を取得
- 画面に表示
MFC版の構造
全体フロー
UI(ダイアログ)
↓
イベントハンドラ
↓
Win32 API
↓
結果をListBoxに表示
ボタンイベント
BEGIN_MESSAGE_MAP(CMainDlg, CDialogEx)
ON_BN_CLICKED(IDC_BTN_GETMAC, &CMainDlg::OnBnClickedGetMac)
END_MESSAGE_MAP()
void CMainDlg::OnBnClickedGetMac()
{
GetMacAddresses();
}
MACアドレス取得(Win32)
ULONG ulSize = 0;
GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &ulSize);
std::vector<BYTE> buffer(ulSize);
PIP_ADAPTER_ADDRESSES pAddrs =
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(buffer.data());
列挙
for (auto p = pAddrs; p != NULL; p = p->Next)
{
// MAC取得
}
UI更新
m_ListBox.AddString(strMac);
MFCの特徴
- UIとロジックが密結合
- メッセージマップでイベント管理
- Win32 API直叩き
- すべてC++で完結
Tauri + Rust版の構造
全体フロー
Svelte(UI)
↓
invoke(JS)
↓
Rust Command
↓
OS API / crate
↓
結果返却
↓
UI更新
Svelte(UI)
<script lang="ts">
import { invoke } from "@tauri-apps/api/core";
let macs: string[] = [];
async function loadMac() {
macs = await invoke<string[]>("get_mac_addresses");
}
</script>
<button on:click={loadMac}>
MAC取得
</button>
{#each macs as mac}
<p>{mac}</p>
{/each}
Rust側(Tauri Command)
#[tauri::command]
fn get_mac_addresses() -> Vec<String> {
use network_interface::NetworkInterface;
use network_interface::NetworkInterfaceConfig;
NetworkInterface::show()
.unwrap()
.into_iter()
.filter_map(|nic| nic.mac_addr)
.map(|mac| mac.to_string())
.collect()
}
コマンド登録
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
get_mac_addresses
])
Tauriの特徴
- UIはWeb技術(Svelte / React / Vue)
- ロジックはRust
- invokeで関数呼び出し
- JSONでデータ通信
MFCとの対応関係
| MFC | Tauri |
|---|---|
| ダイアログ | Svelte |
| ON_BN_CLICKED | on:click |
| C++関数 | Rust command |
| Win32 API | OS / crate |
| ListBox更新 | リアクティブ描画 |
| CString | String |
| CArray | Vec |
一番大きな違い
MFC
イベントの中で全部処理する
UIとロジックが密結合
Tauri
UI(Svelte)
ロジック(Rust)
完全分離
実装感覚の違い
MFC
void CMainDlg::OnBnClicked()
{
GetMac();
UpdateUI();
}
Tauri
UI
↓
invoke()
↓
Rust
↓
戻り値
↓
UI更新
Rust関数の読み方(重要)
ここが分かると一気に読めるようになる。
基本形
fn add(a: i32, b: i32) -> i32 {
a + b
}
読み方
addという関数は
i32型のaとbを受け取って
i32型を返す
中身はa + b
C++との対応
int add(int a, int b)
{
return a + b;
}
戻り値なし
fn log(msg: String) {
println!("{}", msg);
}
値を返さない関数
return省略
fn calc() -> i32 {
10 + 20
}
最後の式が戻り値になる
ifも戻り値になる
fn abs(x: i32) -> i32 {
if x >= 0 {
x
} else {
-x
}
}
分岐そのものが値を返す
Tauriでの意味
Rust関数はほぼローカルAPIとして扱うと分かりやすい。
Svelte
↓ invoke
Rust関数(API)
↓
戻り値
↓
UI更新
まとめ
MACアドレス取得ツールという小さな例でも、
MFCとTauriでは構造が大きく違うように見えるが、本質は同じ「イベント駆動アプリ」である。
違いは1つだけ:
- MFC:すべてC++で完結
- Tauri:UIとロジックが分離
そしてRustは「難しい言語」というより、
C++でやっていた安全でない部分をコンパイラが保証してくれる言語
として見ると理解しやすくなる。