src/lib.rs

lib.rs 是範本的主要原始碼檔案。名稱 lib.rs 通常表示這個 Rust 專案將被編譯為函式庫。

它包含三個關鍵部分

  1. #[wasm_bindgen] 函式
  2. Crate 匯入
  3. wee_alloc 可選依賴項

我們將從 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