src/lib.rs

lib.rs 是模板的主要源文件。名称 lib.rs 通常意味着此 Rust 项目将被编译为库。

它包含三个关键部分

  1. #[wasm_bindgen] 函数
  2. 板条箱导入
  3. wee_alloc 可选依赖项

我们将从 lib.rs 中最重要的部分开始 - 两个 #[wasm_bindgen] 函数(您可以在文件底部找到它们)。在许多情况下,这是您需要修改的 lib.rs 的唯一部分。

1. 使用 wasm_bindgen

为了更方便地从 wasm-bindgen 板条箱公开功能,我们可以使用 use 关键字。use 允许我们方便地引用板条箱或模块的各个部分。您可以在 本书的这一章 中了解更多关于 Rust 如何让您编写模块化代码的信息。


# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#}

许多板条箱包含一个序言,即一个方便一次导入所有内容的列表。这允许模块的常见功能在没有冗长前缀的情况下方便地访问。例如,在这个文件中,我们之所以能够使用 #[wasm_bindgen],是因为它被序言带入了作用域。

use 末尾的星号表示模块 wasm_bindgen::prelude(即板条箱 wasm_bindgen 内的模块 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 可以通过编写 alert("Hello, test-wasm!"); 来调用。

我们知道以这种方式声明 alert,因为这是我们在 JavaScript 中调用 alert 的方式 - 通过向它传递一个字符串参数。


# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub fn greet() {
    alert("Hello, test-wasm!");
}
#}

如果我们在没有 #[wasm_bindgen] 属性的情况下编写 greet 函数,那么 greet 将不容易在 JavaScript 中访问。此外,我们将无法在 JavaScript 和 Rust 之间本机转换某些类型,例如 &str。因此,#[wasm_bindgen] 属性和之前对 alert 的导入都允许从 JavaScript 调用 greet

这就是您需要了解的与 JavaScript 交互的所有内容,至少是入门!您可以通过阅读 wasm-bindgen 文档 来了解更多信息!

如果您对其他内容感到好奇,请继续阅读。

2. 板条箱组织


# #![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