モバイル開発におけるRust:ネイティブモジュールとクロスプラットフォームSDK

著者: IT Sectr 公開日: 2026-02-11 読了時間: 10 分

Rust — コンパイル時にメモリ安全性を保証するシステムプログラミング言語。2010年にGraydon Hoareの指導の下、Mozilla Researchによって開発されました。Rustは、ヌルポインタ、ダングリング参照、データ競合といった脆弱性のクラス全体を防ぎます。モバイル開発では、Rustはネイティブモジュール、クロスプラットフォームSDK、WebAssemblyに使用されています。Stack Overflow Survey(2025)によると、Rustは9年連続で「最も愛されている言語」の第1位です。

重要ポイント

  • Rust — 所有権システムによりガベージコレクタなしでメモリ安全性を実現するシステム言語
  • Borrow checker — コンパイル時に参照をチェックし、データ競合を防ぐ分析ツール
  • ネイティブモジュールはcargo-ndkとcargo-lipoを介して、Android用.so、iOS用.aにコンパイルされます
  • WebAssembly(Wasm)を使用すると、ブラウザやモバイルデバイスでニアネイティブのパフォーマンスでRustコードを実行できます
  • FFI(Foreign Function Interface) — C互換ABIを介してJava、Kotlin、SwiftからRustを呼び出すメカニズム

Rustとは?

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を使用しています。

モバイル開発のための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用)がビルドプロセスを簡素化します。

sh
# モバイル開発のための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 --release

所有権システム:ownership、borrowing、lifetimes

Ownership(所有権)はRustの基本概念です。各値は正確に1つの所有者を持ちます。代入または関数に渡されると、所有権は移動(move)します。移動後、古い所有者はその値を使用できません。これにより、メモリの二重解放とダングリングポインタが排除されます。

Borrowing(借用)を使用すると、所有権を移譲せずに値への参照を一時的に使用できます。&T参照(不変)— 任意の数の読み取り元。&mut T参照(可変)— 正確に1つの書き込み元で、読み取り元はありません。コンパイラはコンパイル時にこれらのルールをチェックします。

rust
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:参照のライフタイム

Lifetimes('a) — 参照のライフタイムを関連付けるアノテーションです。コンパイラはこれらを使用して、参照が指すデータよりも長生きしないことを検証します。ほとんどの場合、ライフタイムは自動的に推論されます — 参照を含む関数シグネチャでのみ指定する必要があります。

rust
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は消滅しました
}

AndroidおよびiOSネイティブモジュール向けRust

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(エミュレータ)が含まれます。

rust
// 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互換型。

例:Rustでの画像処理

rust
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によるクロスプラットフォームSDK

Rustは、単一のコードベースからAndroidとiOSで動作するクロスプラットフォームSDKの理想的な候補です。Mozilla(Firefox)、Dropbox(ファイル同期)、Meta(Libraブロックチェーン)などの企業は、モバイルアプリケーションの重要なコンポーネントにRustを採用しています。

C++に対するRustライブラリの利点:コンパイラがクロスプラットフォームコードでのメモリリークやデータ競合の不在を保証します。Rustで一度作成してテストしたコードは、すべてのプラットフォームで同じように動作します。CargoはCMakeやvcpkgなしで依存関係をネイティブに管理します。

ライブラリ/クレート目的
tonicRust製gRPCクライアント/サーバー
reqwestasync/await対応HTTPクライアント
ring暗号化(AES、RSA、ECDSA)
sqlx非同期SQLite、PostgreSQL
wasm-bindgenRustとJavaScript/WASMの連携
ndk-glueRustでのAndroid NativeActivity
uniffiKotlin/Swift用FFIバインディング生成

モバイルアプリ向けRustとWebAssembly

RustはWebAssembly(Wasm)にコンパイルされます — ブラウザやモバイルデバイスで実行可能なバイナリ形式です。WasmはWeb環境でニアネイティブのパフォーマンスを提供します。モバイル開発では、Wasmはハイブリッドアプリケーション(WebView + Wasm)で複雑な計算(3Dレンダリング、画像認識、暗号化)に使用されます。

wasm-packはRustを.wasmにコンパイルし、JSラッパーを生成します。wasm-bindgenはRust関数をJavaScript呼び出しに接続します。モバイルデバイスでは、WasmランナーはWebView内またはWasmer/Wasmtime SDKを介して実行できます。

rust
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:KotlinとSwiftからRustを呼び出す

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コンポーネントの標準的なアプローチです。

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 vs C++:モバイル開発の比較

RustC++は、モバイル開発におけるシステムプログラミングの2つの主要言語です。どちらもARM向けネイティブコードにコンパイルされ、C ABIを介してFFIをサポートします。主な違いはメモリ安全性モデルです:Rustはコンパイル時にチェックし、C++は開発者の規律に依存します。

基準RustC++
メモリ安全性保証(ownership)開発者の責任
ガベージコレクタなし(RAII + ownership)なし(手動管理)
メモリリークコンパイラが防止可能性あり(newにdeleteなし)
データ競合防止(Send + Sync)可能性あり
Android NDKcargo-ndk経由CMake / NDK Build経由
iOSサポートcargo-lipo + .aXcode + .a
ビルドシステムCargo(内蔵)CMake / Ninja
ビルド時間2~5分(クリーン)5~15分(クリーン)
エコシステムcrates.io(20万+クレート)vcpkg / Conan(10万+ライブラリ)

RustはC++よりも安全で生産的です — コンパイラがC++ではランタイムで顕在化するエラーを捕捉します。C++はより豊富なモバイルライブラリエコシステムを持っています。新規プロジェクトではRustが推奨され、既存のC++コードは段階的に移植されます。

よくある質問

Rustはモバイル開発においてC++とどう違いますか?

主な違いはコンパイル時のメモリ安全性です。Rustには、所有権システムとborrow checkerにより、nullptr、ダングリングポインタ、データ競合がありません。C++は開発者の規律に依存し、Rustはコンパイラのチェックに依存します。

RustはAndroid開発で使用できますか?

はい、Android NDKを介して使用できます。GoogleはAOSP(Android Open Source Project)でRustを公式にサポートしています。Rustはcargo-ndkを介して.soライブラリにコンパイルされます。JNIを介したFFIはC++と同様に機能します。

cargoとは何ですか?Rust開発にどのように役立ちますか?

CargoはRustのパッケージマネージャ兼ビルドシステムです。crates.ioから依存関係をダウンロードし、プロジェクトをコンパイルし、テストを実行します。モバイル開発では、cargo-ndkがCargoを拡張してAndroid ABI向けのクロスコンパイルを可能にします。

RustはiOS向けですか、それともAndroid専用ですか?

Rustは両方のプラットフォームをサポートしています。iOSでは、cargo-lipoを使用してユニバーサルバイナリ(arm64 + x86_64シミュレータ)を作成します。Rustコードは静的.aライブラリにコンパイルされ、Xcodeを介してリンクされます。

2026年にモバイル開発のためにRustを学ぶ価値はありますか?

はい、RustはクロスプラットフォームSDKとネイティブモジュールの標準になりつつあります。Google、Meta、MozillaはRustに投資しています。パフォーマンスクリティカルなコンポーネントでは、RustはC++よりも安全で生産的です。

まとめ

  • Rust — ownership、borrowing、lifetimesによりGCなしでメモリ安全性を実現するシステム言語
  • Borrow checkerがコンパイル時にデータ競合とダングリングポインタを防止
  • ネイティブモジュールはcargo-ndk(Android .so)とcargo-lipo(iOS .a)でビルド
  • UniFFIがKotlinとSwiftのFFIバインディングを生成 — Mozilla標準のモバイルSDK方式
  • WebAssemblyによりモバイルWebViewでRustをニアネイティブ性能で実行可能
  • GoogleがAOSPでRustを採用 — 対象コンポーネントのメモリ脆弱性が70%削減
  • Rust vs C++:Rustはより安全、C++はより豊富なエコシステム、新規ネイティブモジュールにはRust

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください