Rust + WebAssembly 实战教程
1. 环境搭建
首先安装必要的工具链:
# 安装 Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 添加 wasm32 目标
rustup target add wasm32-unknown-unknown
# 安装 wasm-pack
cargo install wasm-pack
2. 创建第一个 WebAssembly 项目
cargo new --lib hello-wasm
cd hello-wasm
修改 Cargo.toml:
[package]
name = "hello-wasm"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
3. 基础 Rust 到 WebAssembly 代码
在 src/lib.rs 中:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
4. 构建和测试
# 构建 wasm 包
wasm-pack build --target web
# 创建测试 HTML 文件
创建 index.html:
<!DOCTYPE html>
<html>
<head>
<title>Rust + WebAssembly Demo</title>
</head>
<body>
<script type="module">
import init, { greet, add } from './pkg/hello_wasm.js';
async function run() {
await init();
// 调用 Rust 函数
greet('World');
// 使用计算结果
const result = add(5, 3);
console.log('5 + 3 =', result);
}
run();
</script>
</body>
</html>
5. 进阶示例:图像处理
use wasm_bindgen::prelude::*;
use web_sys::ImageData;
#[wasm_bindgen]
pub fn grayscale(image_data: &mut [u8]) {
for i in (0..image_data.len()).step_by(4) {
let r = image_data[i] as f32;
let g = image_data[i + 1] as f32;
let b = image_data[i + 2] as f32;
let gray = (0.299 * r + 0.587 * g + 0.114 * b) as u8;
image_data[i] = gray; // R
image_data[i + 1] = gray; // G
image_data[i + 2] = gray; // B
// Alpha 保持不变
}
}
6. 性能优化技巧
- 减少内存分配:重用缓冲区
- 使用 SIMD:利用单指令多数据
- 避免边界检查:使用
get_unchecked
#[wasm_bindgen]
pub fn optimized_process(data: &mut [u8]) {
unsafe {
for i in (0..data.len()).step_by(4) {
let pixel = data.get_unchecked_mut(i..i+4);
// 快速处理像素
}
}
}
7. 调试和测试
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
}
8. 部署建议
- 使用
wasm-pack build --release 进行生产构建
- 考虑使用 wasm-bindgen 的高级特性
- 集成到现有的 JavaScript 框架中
这个教程涵盖了从基础到进阶的 Rust + WebAssembly 开发流程。通过实践这些示例,你可以快速掌握 WebAssembly 开发的核心技能。