今天做的是把跨邊界要用的型別先定成三種——string
、number
、Uint8Array
。字串拿來傳訊息或模式名,數字拿來放參數(在 wasm-bindgen 內部對應 f64
,精度夠、轉換單純),大量資料例如 RGBA 影像,就用連續記憶體的 Uint8Array
,避免在邊界來回序列化巢狀物件。
我們從 兩個檔 wasm/src/lib.rs
跟前端的 demo/src/main.ts
下手:
wasm/src/lib.rs
加三個最小 APIuse wasm_bindgen::prelude::*;
// string 拿來傳訊息、名字、模式名。
#[wasm_bindgen]
pub fn shout(name: &str) -> String {
format!("Hello, {name}!")
}
#[wasm_bindgen]
pub fn add(a: f64, b: f64) -> f64 {
a + b
}
#[wasm_bindgen]
pub fn invert_rgba(input: &[u8], w: u32, h: u32) -> Vec<u8> {
let expected = (w as usize) * (h as usize) * 4; // RGBA 固定 4 通道
if input.len() != expected {
return input.to_vec();
}
let mut out = input.to_vec();
for px in out.chunks_mut(4) {
px[0] = 255 - px[0]; // R
px[1] = 255 - px[1]; // G
px[2] = 255 - px[2]; // B
// A 保留
}
out
}
接著在 demo 上一個資料夾重 build,讓 .js/.d.ts/.wasm
更新:
wasm-pack build --target web --out-dir pkg --out-name rustwasm_test
demo/src/main.ts
用「新版初始化」呼叫這三個 API// 為什麼要這樣 import?—— 先把 wasm 變成穩定 URL,再把它「明講」給 init,避免 MIME / 路徑猜錯。
import init, { shout, add, invert_rgba } from 'rustwasm-test' // 或相對路徑 ./pkg/...
import wasmUrl from 'rustwasm-test/rustwasm_test_bg.wasm?url' // 或 ./pkg/rustwasm_test_bg.wasm?url
// 為什麼用物件參數?—— wasm-bindgen 新版建議寫法,消掉 deprecation 警告,也更明確。
await init({ module: wasmUrl })
// 下面三行就是我們的驗收:字串、數字、位元組都要過邊界、回得來。
console.log(shout('Ali')) // 期望:Hello, Ali!
console.log(add(1.5, 2)) // 期望:3.5
const out = invert_rgba(new Uint8Array([10,20,30,255]), 1, 1)
console.log(out) // 期望:Uint8Array [245,235,225,255]
Console 會印出 Hello, Ali!
、3.5
、以及一段 Uint8Array
;Network 會看到 rustwasm_test_bg.wasm
以 application/wasm
成功載入(200)。