Rust trong phát triển di động: mô-đun gốc và SDK đa nền tảng

Tác giả: IT Sectr Đã đăng: 2026-02-11 Thời gian đọc: 10 phút

Rust — ngôn ngữ lập trình hệ thống với đảm bảo an toàn bộ nhớ tại thời điểm biên dịch. Được phát triển bởi Mozilla Research vào năm 2010 dưới sự chỉ đạo của Graydon Hoare. Rust ngăn chặn toàn bộ các lớp lỗ hổng: con trỏ null, tham chiếu treo và điều kiện đua. Trong phát triển di động, Rust được sử dụng cho các mô-đun gốc, SDK đa nền tảng và WebAssembly. Theo Stack Overflow Survey (2025), Rust đứng đầu về «ngôn ngữ được yêu thích nhất» năm thứ chín liên tiếp.

Những điểm chính

  • Rust — ngôn ngữ hệ thống với an toàn bộ nhớ không cần bộ thu gom rác thông qua hệ thống quyền sở hữu (ownership)
  • Borrow checker — trình phân tích kiểm tra tham chiếu tại thời điểm biên dịch, ngăn chặn điều kiện đua
  • Mô-đun gốc trong Rust biên dịch thành .so cho Android và .a cho iOS qua cargo-ndk và cargo-lipo
  • WebAssembly (Wasm) cho phép chạy mã Rust trong trình duyệt và trên thiết bị di động với hiệu suất gần như gốc
  • FFI (Giao diện Hàm Ngoại lai) — cơ chế gọi Rust từ Java, Kotlin và Swift thông qua ABI tương thích C

Rust là gì?

Rust là ngôn ngữ lập trình hệ thống được định kiểu tĩnh với các trừu tượng không chi phí (zero-cost abstractions). Rust đảm bảo an toàn bộ nhớ không cần bộ thu gom rác nhờ hệ thống quyền sở hữu (ownership), vay mượn (borrowing) và thời gian sống (lifetimes). Trình biên dịch Rust là một trong những trình nghiêm ngặt nhất: nó từ chối mã mà trong C++ sẽ gây ra hành vi không xác định.

Rust biên dịch qua LLVM thành mã gốc cho tất cả kiến trúc: ARM, x86, RISC-V, WebAssembly. Bộ công cụ bao gồm: rustup (trình cài đặt), rustc (trình biên dịch), cargo (trình quản lý gói và xây dựng). Cargo.toml — tương tự package.json, chứa các phụ thuộc từ crates.io. Phiên bản ổn định mới nhất là Rust 1.81 (2025).

Các lĩnh vực ứng dụng chính của Rust trong phát triển di động: thư viện gốc (Android NDK, iOS), SDK đa nền tảng (Firefox, Dropbox), thay thế C++ trong các phần quan trọng về hiệu suất, WebAssembly cho ứng dụng lai. Google sử dụng Rust trong AOSP (Android Open Source Project) cho các thành phần Bluetooth, Wi-Fi và NFC.

Cài đặt và cấu hình Rust cho phát triển di động

Để biên dịch chéo cho Android, cần có chuỗi công cụ đích: rustup target add aarch64-linux-android armv7-linux-androideabi. Cho iOS — aarch64-apple-ios x86_64-apple-ios. cargo-ndk (cho Android) và cargo-lipo (cho iOS) đơn giản hóa quá trình xây dựng.

sh
# Cài đặt Rust và nền tảng đích cho phát triển di động
$ 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

# Cài đặt cargo-ndk cho bản dựng Android
$ cargo install cargo-ndk

# Xây dựng cho Android
$ cargo ndk -t arm64-v8a -o ./jniLibs build --release

Hệ thống quyền sở hữu: ownership, borrowing và lifetimes

Ownership (quyền sở hữu) là khái niệm nền tảng của Rust. Mỗi giá trị có chính xác một chủ sở hữu. Khi được gán hoặc truyền vào hàm, quyền sở hữu được di chuyển (move). Sau khi di chuyển, chủ sở hữu cũ không thể sử dụng giá trị. Điều này loại bỏ việc giải phóng bộ nhớ kép và con trỏ treo.

Borrowing (vay mượn) cho phép sử dụng tạm thời tham chiếu đến một giá trị mà không chuyển quyền sở hữu. Tham chiếu &T (bất biến) — số lượng người đọc không giới hạn. Tham chiếu &mut T (khả biến) — chính xác một người viết, không có người đọc. Trình biên dịch kiểm tra các quy tắc này tại thời điểm biên dịch.

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];  // vay mượn bất biến
    println!("First: {}", first);
}

process_data nhận một tham chiếu khả biến đến Vec và nhân đôi mỗi phần tử. iter_mut() trả về một trình vòng lặp với các tham chiếu khả biến. *item giải tham chiếu để gán. Sau process_data, numbers vẫn có thể truy cập — quyền sở hữu không bị chuyển, chỉ được mượn.

Lifetimes: thời gian sống của tham chiếu

Lifetimes ('a) — chú thích liên kết thời gian sống của các tham chiếu. Trình biên dịch sử dụng chúng để xác minh rằng tham chiếu không tồn tại lâu hơn dữ liệu mà nó trỏ đến. Trong hầu hết các trường hợp, lifetimes được suy luận tự động — bạn chỉ cần chỉ định chúng trong chữ ký hàm có tham chiếu.

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 sống đến dấu ngoặc nhọn này, result hợp lệ bên trong
    // println!("{}", result); // lỗi: string2 đã chết
}

Rust cho mô-đun gốc Android và iOS

Rust biên dịch thành thư viện gốc cho Android (.so qua NDK) và iOS (.a thư viện tĩnh). Google chính thức hỗ trợ Rust trong Android Open Source Project (AOSP) — Rust được sử dụng cho các thành phần Bluetooth (ava), DNS-over-HTTP3 và CriticalNotification. Theo Google (2025), Rust trong Android đã loại bỏ 70% lỗ hổng bộ nhớ trong các thành phần mục tiêu.

Cho Android, cargo-ndk được sử dụng, nó bọc Cargo với chuỗi công cụ chính xác cho ABI đã chọn. Xây dựng cho Android bao gồm: aarch64-linux-android (ARM 64-bit, thiết bị hiện đại), armv7-linux-androideabi (ARM 32-bit), x86_64-linux-android (trình giả lập).

rust
// Cargo.toml — cấu hình thư viện cho 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 — cho iOS (.a), cdylib — cho Android (.so). serde — tuần tự hóa để trao đổi dữ liệu với Kotlin/Swift. libc — kiểu tương thích C cho FFI.

Ví dụ: xử lý ảnh trong Rust

rust
use std::ffi::{CStr, CString};
use std::os::raw::c_char;

/// Hàm tương thích C để xử lý ảnh
#[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] vô hiệu hóa name mangling cho ABI tương thích C. extern "C" chỉ định quy ước gọi C. unsafe — điểm đánh dấu rằng việc gọi từ bên ngoài Rust không đảm bảo an toàn. std::ptr::copy_nonoverlapping sao chép byte kết quả vào bộ đệm đầu ra.

SDK đa nền tảng trong Rust

Rust là ứng cử viên lý tưởng cho SDK đa nền tảng hoạt động trên Android và iOS từ một mã nguồn duy nhất. Các công ty như Mozilla (Firefox), Dropbox (đồng bộ tệp) và Meta (blockchain Libra) đã chọn Rust cho các thành phần quan trọng trong ứng dụng di động của họ.

Lợi thế của thư viện Rust so với C++: trình biên dịch đảm bảo không có rò rỉ bộ nhớ và điều kiện đua trong mã đa nền tảng. Mã viết và kiểm thử trong Rust hoạt động giống hệt nhau trên tất cả nền tảng. Cargo quản lý phụ thuộc một cách gốc, không cần CMake hay vcpkg.

Thư viện/CrateMục đích
tonicMáy khách/máy chủ gRPC trong Rust
reqwestMáy khách HTTP với async/await
ringMật mã học (AES, RSA, ECDSA)
sqlxSQLite, PostgreSQL bất đồng bộ
wasm-bindgenTích hợp Rust với JavaScript/WASM
ndk-glueAndroid NativeActivity trong Rust
uniffiTạo liên kết FFI cho Kotlin/Swift

Rust và WebAssembly cho ứng dụng di động

Rust biên dịch sang WebAssembly (Wasm) — định dạng nhị phân có thể thực thi trong trình duyệt và trên thiết bị di động. Wasm cung cấp hiệu suất gần như gốc trong môi trường web. Trong phát triển di động, Wasm được sử dụng trong ứng dụng lai (WebView + Wasm) cho các tính toán phức tạp: kết xuất 3D, nhận dạng ảnh, mã hóa.

wasm-pack biên dịch Rust thành .wasm và tạo trình bọc JS. wasm-bindgen kết nối các hàm Rust với lệnh gọi JavaScript. Trên thiết bị di động, trình chạy Wasm có thể chạy trong WebView hoặc qua SDK Wasmer/Wasmtime.

rust
use wasm_bindgen::prelude::*;

/// Tính số Fibonacci trong Wasm (được gọi từ 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] tạo trình bọc JavaScript cho hàm fibonacci. Trong trình duyệt, lệnh gọi trông như wasm.fibonacci(10). Các kiểu u32/u64 tự động chuyển đổi thành Number/BigInt. Mô-đun Wasm chỉ nặng ~5 KB cho một hàm như vậy — chi phí tối thiểu.

FFI: gọi Rust từ Kotlin và Swift

FFI (Foreign Function Interface) — cơ chế gọi mã Rust từ các ngôn ngữ khác. Các hàm Rust với extern "C" và #[no_mangle] được xuất với ABI tương thích C. Từ Kotlin, các hàm này được gọi qua JNI, từ Swift — qua @_cdecl ("name") hoặc CBridge.h.

UniFFI — công cụ Mozilla để tạo liên kết FFI. Bạn mô tả API trong tệp .udl và UniFFI tự động tạo trình bọc Kotlin và Swift. Đây là cách tiếp cận tiêu chuẩn cho các thành phần Rust trong Firefox Android và Firefox iOS.

rust
// Thư viện Rust với giao diện UniFFI
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> {
    // triển khai AES-256-GCM
    todo!()
}

UniFFI tạo một lớp Kotlin với phương thức encrypt, nhận ByteArray và trả về EncryptedData. Trong Swift, một cấu trúc EncryptedData được tạo với các trường ciphertext (Data) và nonce (Data). Lỗi được chuyển đổi thành ngoại lệ Kotlin/Swift.

Rust so với C++: so sánh cho phát triển di động

RustC++ là hai ngôn ngữ chính cho lập trình hệ thống trong phát triển di động. Cả hai đều biên dịch thành mã gốc ARM và hỗ trợ FFI qua ABI C. Sự khác biệt chính là mô hình an toàn bộ nhớ: Rust kiểm tra tại thời điểm biên dịch, C++ dựa vào kỷ luật của lập trình viên.

Tiêu chíRustC++
An toàn bộ nhớĐảm bảo (ownership)Trách nhiệm lập trình viên
Bộ thu gom rácKhông (RAII + ownership)Không (quản lý thủ công)
Rò rỉ bộ nhớTrình biên dịch ngăn chặnCó thể (new không delete)
Điều kiện đuaNgăn chặn (Send + Sync)Có thể
Android NDKQua cargo-ndkQua CMake / NDK Build
Hỗ trợ iOScargo-lipo + .aXcode + .a
Hệ thống xây dựngCargo (tích hợp)CMake / Ninja
Thời gian xây dựng2–5 phút (sạch)5–15 phút (sạch)
Hệ sinh tháicrates.io (200k+ crates)vcpkg / Conan (100k+ thư viện)

Rust an toàn hơn C++ và năng suất hơn — trình biên dịch bắt lỗi mà trong C++ sẽ xuất hiện khi chạy. C++ có hệ sinh thái thư viện di động phong phú hơn. Cho dự án mới, Rust được ưu tiên; mã C++ hiện có được chuyển đổi dần dần.

Câu hỏi thường gặp

Rust khác C++ như thế nào trong phát triển di động?

Sự khác biệt chính là an toàn bộ nhớ tại thời điểm biên dịch. Rust không có nullptr, con trỏ treo hay điều kiện đua nhờ hệ thống quyền sở hữu và borrow checker. C++ dựa vào kỷ luật lập trình viên, Rust dựa vào kiểm tra của trình biên dịch.

Có thể sử dụng Rust trong phát triển Android không?

Có, qua Android NDK. Google chính thức hỗ trợ Rust trong AOSP (Android Open Source Project). Rust biên dịch thành thư viện .so qua cargo-ndk. FFI (Foreign Function Interface) qua JNI hoạt động giống như cho C++.

cargo là gì và nó giúp ích gì trong phát triển Rust?

Cargo là trình quản lý gói và hệ thống xây dựng của Rust. Nó tải phụ thuộc từ crates.io, biên dịch dự án và chạy kiểm thử. Trong phát triển di động, cargo-ndk mở rộng Cargo để biên dịch chéo cho ABI Android.

Rust phù hợp cho iOS hay chỉ Android?

Rust hỗ trợ cả hai nền tảng. Cho iOS, cargo-lipo được sử dụng để tạo tệp nhị phân phổ quát (arm64 + x86_64 trình giả lập). Mã Rust biên dịch thành thư viện tĩnh .a và được liên kết qua Xcode.

Có đáng học Rust cho phát triển di động trong năm 2026 không?

Có, Rust đang trở thành tiêu chuẩn cho SDK đa nền tảng và mô-đun gốc. Google, Meta và Mozilla đang đầu tư vào Rust. Cho các thành phần quan trọng về hiệu suất, Rust an toàn và năng suất hơn C++.

Tổng kết

  • Rust — ngôn ngữ hệ thống với an toàn bộ nhớ không GC nhờ ownership, borrowing và lifetimes
  • Borrow checker ngăn chặn điều kiện đua và con trỏ treo tại thời điểm biên dịch
  • Mô-đun gốc được xây dựng qua cargo-ndk (Android .so) và cargo-lipo (iOS .a)
  • UniFFI tạo liên kết FFI cho Kotlin và Swift — tiêu chuẩn Mozilla cho SDK di động
  • WebAssembly cho phép chạy Rust trong WebView di động với hiệu suất gần như gốc
  • Google sử dụng Rust trong AOSP — lỗ hổng bộ nhớ trong thành phần mục tiêu giảm 70%
  • Rust so với C++: Rust an toàn hơn, C++ có hệ sinh thái phong phú hơn; cho mô-đun gốc mới, Rust được ưu tiên

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm