如何将字符串值从 JavaScript 传入 Wasm/Rust

本文所用的所有资源都可以在 https://github.com/second-sta... 中找到

系列教程:

  1. WebAssembly 快问快答
  2. Rust 的 Hello world | WebAssembly 入门教程
  3. 5分钟实现一个简单的 WebAssembly 应用|WebAssembly 入门教程

在前面的教程中,我们提到了 WebAssembly 应用程序通常由两部分组成:

  • 运行在 WebAssembly 虚拟机内部的字节码程序
  • 调用 WebAssembly 程序的主机应用程序

然而,轻量级的 WebAssembly 虚拟机只支持非常有限的数值数据类型。 另一方面,主机应用程序可能需要处理复杂的数据类型。 字符串就属于这种复杂的数据类型。

字符串是复杂的,因为它包含大小未知和结构未知的数据(即编码)。 主机应用程序不能直接在 WebAssembly 之间传递字符串数据。 它必须将字符串值与数值和数组相互转换。

《WebAssembly 中的字符串》会让你对字符串有更深的了解

这个教程将展示如何构建一个真正的“ hello world” 以及如何在 WebAssembly 中处理字符串。

  • 主机应用程序是用 JavaScript 编写的,在 Web 浏览器中运行。 它在 WebAssembly 函数调用之间传递字符串。
  • WebAssembly 字节码程序是用 Rust 编写的。 它以 Rust String 结构的形式接收和返回字符串。
教程的源代码在这里

设置

我们在这个示例中介绍的重要开发工具是 wasm-pack。 它将 Rust 源代码编译成一个 WebAssembly 字节码程序,然后生成一个 JavaScript 模块,该模块可以与 WebAssembly 程序交互。 生成的代码负责输入/输出数据的编码和管理, 这使得 JavaScript 开发者更容易调用 WebAssembly 函数。

按照下面的步骤安装 Rust 和 wasm-pack工具。

# Install Rust

$ sudo apt-get update
$ sudo apt-get -y upgrade
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ source $HOME/.cargo/env
# Install wasm-pack tools

$ curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

Rust 写的 WebAssembly 程序

在这个示例中,Rust 程序在“ hello”后面追加输入字符串。 让我们创建一个新的 cargo项目。 由于这个程序是从主机应用程序调用的,而不是作为独立的可执行文件运行,因此我们将创建一个 hello 项目。

$ cargo new --lib hello
$ cd hello

编辑 Cargo.toml 文件,添加一个[lib] 部分。 它会告诉编译器在哪里可以找到库的源代码,以及如何生成字节码输出。 这里我们还需要一个 wasm-bindgen 的依赖项。是实用的wasm-pack 为 Rust WebAssembly 程序生成 JavaScript 绑定。

[lib]
name = "hello_lib"
path = "src/lib.rs"
crate-type =["cdylib"]
[dependencies]
wasm-bindgen = "0.2.50"

下面是Rust 程序 src/lib.rs的内容。实际上,我们可以在这个库文件中定义多个外部函数,并且所有这些函数都可以通过 WebAssembly 在主机 JavaScript 应用程序中使用。 #[wasm_bindgen] 标签指示构建工具在 Rust / WebAssembly 和 JavaScript 模块中生成通信接口。

use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn say(s: String) -> String {
  let r = String::from("hello ");
  return r + &s;
}

接下来,将 Rust 源代码编译成 WebAssembly 字节码,并生成相应的 JavaScript 模块。

$ wasm-pack build --target web

结果是下面两个de 文件。.wasm文件是 WebAssembly 字节码程序,.js 文件是JavaScript模块。

pkg/hello_lib_bg.wasm
pkg/hello_lib.js

JavaScript主机

让我们回到 JavaScript 主机应用。有了生成的 hello_lib.js 模块,可以非常容易地写 JavaScript 来调用 WebAssembly 函数。在 import 之后, WebAssembly say() 函数现在成了一个同名的JavaScript 函数。完整的网页源文件在这里

<script type="module">
  import init, { say } from './hello_lib.js';
  async function run() {
    await init();
    var buttonOne = document.getElementById('buttonOne');
    buttonOne.addEventListener('click', function() {
      var input = $("#nameInput").val();
      alert(say(input));
    }, false);
  }
  run();
</script>

hello_lib_bg.wasm 程序是由hello_lib.js 模块加载, 将HTML 文件 hello_lib.jshello_lib_bg.wasm 文件放在网络服务器上,现在得到了一个在输入任何名称都能 "say hello" 的网页了。

下一步是什么呢?

到目前为止,我们已经了解了如何从托管在浏览器中的 JavaScript 访问 WebAssembly 程序。 但更重要的是,我们相信 WebAssembly 真正的潜力在于服务器端。 在下一个教程中,我们将关注服务器端的 WebAssembly 示例!


WASM中文社区
169 声望162 粉丝