Rust — コンパイル時にメモリ安全性を保証するシステムプログラミング言語。2010年にGraydon Hoareの指導の下、Mozilla Researchによって開発されました。Rustは、ヌルポインタ、ダングリング参照、データ競合といった脆弱性のクラス全体を防ぎます。モバイル開発では、Rustはネイティブモジュール、クロスプラットフォームSDK、WebAssemblyに使用されています。Stack Overflow Survey(2025)によると、Rustは9年連続で「最も愛されている言語」の第1位です。
重要ポイント
Rustは、ゼロコスト抽象化を備えた静的型付きシステムプログラミング言語です。Rustは、所有権(ownership)、借用(borrowing)、ライフタイム(lifetimes)のシステムにより、ガベージコレクタなしでメモリ安全性を保証します。Rustコンパイラは最も厳格なものの一つで、C++で未定義動作を引き起こすコードを拒否します。
RustはLLVMを介して、ARM、x86、RISC-V、WebAssemblyなどすべてのアーキテクチャ向けのネイティブコードにコンパイルされます。ツールチェーンには、rustup(インストーラ)、rustc(コンパイラ)、cargo(パッケージマネージャ兼ビルドツール)が含まれます。Cargo.tomlはpackage.jsonに似ており、crates.ioからの依存関係を含みます。最新の安定版はRust 1.81(2025年)です。
モバイル開発におけるRustの主な適用分野:ネイティブライブラリ(Android NDK、iOS)、クロスプラットフォームSDK(Firefox、Dropbox)、パフォーマンスクリティカルな部分でのC++の置き換え、ハイブリッドアプリケーション向けWebAssembly。GoogleはAOSP(Android Open Source Project)でBluetooth、Wi-Fi、NFCコンポーネントにRustを使用しています。
Android向けのクロスコンパイルには、ターゲットツールチェーンが必要です:rustup target add aarch64-linux-android armv7-linux-androideabi。iOS向け — aarch64-apple-ios x86_64-apple-ios。cargo-ndk(Android用)とcargo-lipo(iOS用)がビルドプロセスを簡素化します。
# モバイル開発のためのRustとターゲットプラットフォームのインストール
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ rustup target add aarch64-linux-android
$ rustup target add armv7-linux-androideabi
$ rustup target add aarch64-apple-ios
$ rustup target add x86_64-apple-ios
# Androidビルド用のcargo-ndkのインストール
$ cargo install cargo-ndk
# Android向けビルド
$ cargo ndk -t arm64-v8a -o ./jniLibs build --releaseOwnership(所有権)はRustの基本概念です。各値は正確に1つの所有者を持ちます。代入または関数に渡されると、所有権は移動(move)します。移動後、古い所有者はその値を使用できません。これにより、メモリの二重解放とダングリングポインタが排除されます。
Borrowing(借用)を使用すると、所有権を移譲せずに値への参照を一時的に使用できます。&T参照(不変)— 任意の数の読み取り元。&mut T参照(可変)— 正確に1つの書き込み元で、読み取り元はありません。コンパイラはコンパイル時にこれらのルールをチェックします。
fn process_data(data: &mut Vec<i32>) {
for item in data.iter_mut() {
*item *= 2;
}
}
fn main() {
let mut numbers = vec![1, 2, 3, 4, 5];
process_data(&mut numbers);
println!("Processed: {:?}", numbers);
let first = &numbers[0]; // 不変の借用
println!("First: {}", first);
}process_dataはVecへの可変参照を受け取り、各要素を2倍にします。iter_mut()は可変参照を持つイテレータを返します。*itemは代入のために参照をデリファレンスします。process_dataの後もnumbersはアクセス可能です — 所有権は移動せず、借用のみです。
Lifetimes('a) — 参照のライフタイムを関連付けるアノテーションです。コンパイラはこれらを使用して、参照が指すデータよりも長生きしないことを検証します。ほとんどの場合、ライフタイムは自動的に推論されます — 参照を含む関数シグネチャでのみ指定する必要があります。
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
fn main() {
let string1 = String::from("rust");
let result;
{
let string2 = String::from("mobile");
result = longest(string1.as_str(), string2.as_str());
println!("Longest: {}", result);
} // string2はこの中括弧まで生存、resultは内部で有効
// println!("{}", result); // エラー:string2は消滅しました
}Rustは、Android(NDK経由の.so)およびiOS(.a静的ライブラリ)向けのネイティブライブラリにコンパイルされます。GoogleはAndroid Open Source Project(AOSP)でRustを公式にサポートしており、Bluetooth(ava)、DNS-over-HTTP3、CriticalNotificationの各コンポーネントにRustが使用されています。Google(2025年)によると、AndroidのRustは対象コンポーネントのメモリ脆弱性を70%削減しました。
Androidでは、選択したABIに適したツールチェーンでCargoをラップするcargo-ndkが使用されます。Android向けビルドには、aarch64-linux-android(64ビットARM、最新デバイス)、armv7-linux-androideabi(32ビットARM)、x86_64-linux-android(エミュレータ)が含まれます。
// Cargo.toml — Android/iOS用ライブラリ設定
[package]
name = "mobile_crypto"
version = "0.1.0"
[lib]
crate-type = ["staticlib", "cdylib"]
[dependencies]
serde = { version = "1", features = ["derive"] }
libc = "0.2"crate-type:staticlib — iOS(.a)用、cdylib — Android(.so)用。serde — Kotlin/Swiftとのデータ交換のためのシリアル化。libc — FFI用のC互換型。
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
/// 画像処理のためのC互換関数
#[no_mangle]
pub unsafe extern "C" fn process_image(
input: *const u8,
len: usize,
output: *mut u8,
out_len: *mut usize,
) {
let input_slice = std::slice::from_raw_parts(input, len);
let result: Vec<u8> = input_slice.iter()
.map(|b| b ^ 0xFF)
.collect();
let result_len = result.len();
std::ptr::copy_nonoverlapping(result.as_ptr(), output, result_len);
*out_len = result_len;
}#[no_mangle]はC互換ABIの名前マングリングを無効にします。extern "C"はC呼び出し規則を指定します。unsafe — Rust外部からの呼び出しが安全性を保証しないことを示すマーカーです。std::ptr::copy_nonoverlappingは結果のバイトを出力バッファにコピーします。
Rustは、単一のコードベースからAndroidとiOSで動作するクロスプラットフォームSDKの理想的な候補です。Mozilla(Firefox)、Dropbox(ファイル同期)、Meta(Libraブロックチェーン)などの企業は、モバイルアプリケーションの重要なコンポーネントにRustを採用しています。
C++に対するRustライブラリの利点:コンパイラがクロスプラットフォームコードでのメモリリークやデータ競合の不在を保証します。Rustで一度作成してテストしたコードは、すべてのプラットフォームで同じように動作します。CargoはCMakeやvcpkgなしで依存関係をネイティブに管理します。
| ライブラリ/クレート | 目的 |
|---|---|
| tonic | Rust製gRPCクライアント/サーバー |
| reqwest | async/await対応HTTPクライアント |
| ring | 暗号化(AES、RSA、ECDSA) |
| sqlx | 非同期SQLite、PostgreSQL |
| wasm-bindgen | RustとJavaScript/WASMの連携 |
| ndk-glue | RustでのAndroid NativeActivity |
| uniffi | Kotlin/Swift用FFIバインディング生成 |
RustはWebAssembly(Wasm)にコンパイルされます — ブラウザやモバイルデバイスで実行可能なバイナリ形式です。WasmはWeb環境でニアネイティブのパフォーマンスを提供します。モバイル開発では、Wasmはハイブリッドアプリケーション(WebView + Wasm)で複雑な計算(3Dレンダリング、画像認識、暗号化)に使用されます。
wasm-packはRustを.wasmにコンパイルし、JSラッパーを生成します。wasm-bindgenはRust関数をJavaScript呼び出しに接続します。モバイルデバイスでは、WasmランナーはWebView内またはWasmer/Wasmtime SDKを介して実行できます。
use wasm_bindgen::prelude::*;
/// Wasmでのフィボナッチ数計算(JSから呼び出し)
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => {
let mut a = 0;
let mut b = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
}
}#[wasm_bindgen]はfibonacci関数のJavaScriptラッパーを生成します。ブラウザでは、wasm.fibonacci(10)のように呼び出します。u32/u64型は自動的にNumber/BigIntに変換されます。このような関数のWasmモジュールはわずか〜5KBと最小限のオーバーヘッドです。
FFI(Foreign Function Interface) — 他の言語からRustコードを呼び出すためのメカニズムです。extern "C"と#[no_mangle]を付けたRust関数は、C互換ABIでエクスポートされます。KotlinからはJNIを介して、Swiftからは@_cdecl("name")またはCBridge.hを介して呼び出されます。
UniFFI — FFIバインディングを生成するMozillaのツールです。.udlファイルにAPIを記述すると、UniFFIが自動的にKotlinとSwiftのラッパーを生成します。これはFirefox AndroidとFirefox iOSのRustコンポーネントの標準的なアプローチです。
// UniFFIインターフェース付きRustライブラリ
uniffi::setup_scaffolding!();
#[derive(uniffi::Enum)]
pub enum EncryptionError {
InvalidKey,
EncryptionFailed,
}
#[derive(uniffi::Record)]
pub struct EncryptedData {
pub ciphertext: Vec<u8>,
pub nonce: Vec<u8>,
}
#[uniffi::export]
pub fn encrypt(key: &[u8], plaintext: &[u8]) -> Result<EncryptedData, EncryptionError> {
// AES-256-GCM実装
todo!()
}UniFFIは、ByteArrayを受け取りEncryptedDataを返すencryptメソッドを持つKotlinクラスを生成します。Swiftでは、ciphertext(Data)とnonce(Data)フィールドを持つEncryptedData構造体が作成されます。エラーはKotlin/Swiftの例外に変換されます。
RustとC++は、モバイル開発におけるシステムプログラミングの2つの主要言語です。どちらもARM向けネイティブコードにコンパイルされ、C ABIを介してFFIをサポートします。主な違いはメモリ安全性モデルです:Rustはコンパイル時にチェックし、C++は開発者の規律に依存します。
| 基準 | Rust | C++ |
|---|---|---|
| メモリ安全性 | 保証(ownership) | 開発者の責任 |
| ガベージコレクタ | なし(RAII + ownership) | なし(手動管理) |
| メモリリーク | コンパイラが防止 | 可能性あり(newにdeleteなし) |
| データ競合 | 防止(Send + Sync) | 可能性あり |
| Android NDK | cargo-ndk経由 | CMake / NDK Build経由 |
| iOSサポート | cargo-lipo + .a | Xcode + .a |
| ビルドシステム | Cargo(内蔵) | CMake / Ninja |
| ビルド時間 | 2~5分(クリーン) | 5~15分(クリーン) |
| エコシステム | crates.io(20万+クレート) | vcpkg / Conan(10万+ライブラリ) |
RustはC++よりも安全で生産的です — コンパイラがC++ではランタイムで顕在化するエラーを捕捉します。C++はより豊富なモバイルライブラリエコシステムを持っています。新規プロジェクトではRustが推奨され、既存のC++コードは段階的に移植されます。
よくある質問
主な違いはコンパイル時のメモリ安全性です。Rustには、所有権システムとborrow checkerにより、nullptr、ダングリングポインタ、データ競合がありません。C++は開発者の規律に依存し、Rustはコンパイラのチェックに依存します。
はい、Android NDKを介して使用できます。GoogleはAOSP(Android Open Source Project)でRustを公式にサポートしています。Rustはcargo-ndkを介して.soライブラリにコンパイルされます。JNIを介したFFIはC++と同様に機能します。
CargoはRustのパッケージマネージャ兼ビルドシステムです。crates.ioから依存関係をダウンロードし、プロジェクトをコンパイルし、テストを実行します。モバイル開発では、cargo-ndkがCargoを拡張してAndroid ABI向けのクロスコンパイルを可能にします。
Rustは両方のプラットフォームをサポートしています。iOSでは、cargo-lipoを使用してユニバーサルバイナリ(arm64 + x86_64シミュレータ)を作成します。Rustコードは静的.aライブラリにコンパイルされ、Xcodeを介してリンクされます。
はい、RustはクロスプラットフォームSDKとネイティブモジュールの標準になりつつあります。Google、Meta、MozillaはRustに投資しています。パフォーマンスクリティカルなコンポーネントでは、RustはC++よりも安全で生産的です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。