src/lib.rs
lib.rs
是範本的主要原始碼檔案。名稱 lib.rs
通常表示這個 Rust 專案將被編譯為函式庫。
它包含三個關鍵部分
我們將從 lib.rs
最重要的部分開始 - 兩個 #[wasm_bindgen]
函式(你可以在檔案底部找到)。在許多情況下,這是你唯一需要修改的 lib.rs
部分。
1. 使用 wasm_bindgen
為了更方便地從 wasm-bindgen
crate 公開功能,我們可以使用 use
關鍵字。use
允許我們方便地參考 crate 或模組的部分內容。你可以在本書的這一章中學習更多關於 Rust 如何讓你編寫模組化程式碼的知識。
# #![allow(unused_variables)] #fn main() { use wasm_bindgen::prelude::*; #}
許多 crate 都包含一個前奏曲,其中列出了可以一次性匯入的所有內容。這允許在不使用冗長前綴的情況下方便地存取模組的常用功能。例如,在這個檔案中,我們可以使用 #[wasm_bindgen]
,僅僅因為它是由前奏曲引入作用域的。
這個 use
結尾的星號表示 wasm_bindgen::prelude
模組(即 wasm_bindgen
crate 內的 prelude
模組)中的所有內容都可以在不使用 wasm_bindgen::prelude
前綴的情況下被參考。
例如,#[wasm_bindgen]
也可以寫成 #[wasm_bindgen::prelude::wasm_bindgen]
,儘管不建議這樣做。
1. #[wasm_bindgen]
函式
#[wasm_bindgen]
屬性表示它下面的函式在 JavaScript 和 Rust 中都可以存取。
# #![allow(unused_variables)] #fn main() { #[wasm_bindgen] extern { fn alert(s: &str); } #}
extern
區塊將外部 JavaScript 函式 alert
匯入到 Rust 中。這個宣告是從 Rust 中呼叫 alert
所必需的。通過這種方式宣告,wasm-bindgen
將為 alert
建立 JavaScript 存根,允許我們在 Rust 和 JavaScript 之間來回傳遞字串。
我們可以看到 alert
函式需要一個類型為 &str
的參數 s
,即一個字串。在 Rust 中,任何字串字面量(例如 "Hello, test-wasm!"
)的類型都是 &str
。因此,可以通過編寫 alert("Hello, test-wasm!");
來呼叫 alert
。
我們之所以知道要這樣宣告 alert
,是因為這就是我們在 JavaScript 中呼叫 alert
的方式 - 通過向它傳遞一個字串參數。
# #![allow(unused_variables)] #fn main() { #[wasm_bindgen] pub fn greet() { alert("Hello, test-wasm!"); } #}
如果我們在沒有 #[wasm_bindgen]
屬性的情況下編寫 greet
函式,那麼 greet
將無法在 JavaScript 中輕鬆存取。此外,我們將無法在本機將某些類型(例如 &str
)在 JavaScript 和 Rust 之間進行轉換。因此,#[wasm_bindgen]
屬性和先前對 alert
的匯入都允許從 JavaScript 中呼叫 greet
。
這就是與 JavaScript 互動所需知道的全部內容,至少就目前而言!你可以通過閱讀wasm-bindgen
文件了解更多資訊!
如果你對其餘部分感到好奇,請继续阅读。
2. Crate 組織
# #![allow(unused_variables)] #fn main() { mod utils; #}
這條語句宣告了一個名為 utils
的新模組,它由 utils.rs
的內容定義。等效地,我們可以將 utils.rs
的內容放在 utils
宣告中,將該行替換為
# #![allow(unused_variables)] #fn main() { mod utils { // contents of utils.rs } #}
無論哪種方式,utils.rs
的內容都定義了一個公共函式 set_panic_hook
。因為我們將它放在 utils
模組中,所以我們將能夠通過編寫 utils::set_panic_hook()
直接呼叫該函式。我們將在 src/utils.rs
中討論如何以及為什麼要使用這個函式。
# #![allow(unused_variables)] #fn main() { // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global // allocator. if #[cfg(feature = "wee_alloc")] { #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #}
在編譯時,這將測試是否為此編譯啟用了 wee_alloc
功能。如果啟用了,我們將配置一個全局分配器(根據wee_alloc
的文件),否則它將被編譯為空。
正如我們之前看到的,[features]
中的 default
向量只包含 "console_error_panic_hook"
,而不包含 "wee_alloc"
。因此,在這種情況下,這個區塊將被替換為任何程式碼,因此將使用預設的記憶體分配器而不是 wee_alloc
。