将 Rust 程序编译为 WebAssembly 的知识与实践
作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/130859548
【介绍】:本文记叙如何将一个 Rust 语言编译成可执行的 WebAssembly 文件。
- 1. 概述
- 2. 快速入门 Rust-WebAssembly
- 2.1 搭建 Rust 开发环境
- 2.2 编写你的 Rust 代码
- 2.3 在当前项目中添加 wasm_bindgen 和 wasm-pack 模块
- 2.4 可能用到的各种各种工具
- 2.5 构建基于 wasm 的 npm 模块
- 3. 关于
wasm-pack
模块 - 4. 小结
- 5. 关于编译出来的 pkg 项目
WebAssembly 是一种低级的类汇编语言,它是一种可以在现代的网络浏览器中运行的新的编码方式,并且可以接近原生的性能运行。依据官网的介绍,WebAssembly(缩写为 Wasm)是 基于堆栈的虚拟机 的 二进制指令格式。Wasm被设计为编程语言的可移植编译目标,支持 客户端和服务器应用程序 在 Web 上的部署。
通过 WebAssembly 技术,我们可以为 Rust、C / C ++、Go 等多种语言提供一个编译目标,以便它们可以在 Web 上运行,并且是可以与 JavaScript 一起工作的。
WebAssembly 官方对于该技术的优势归纳为以下几个方面:高效、安全、开放。
Wasm堆栈机被设计为 以 大小 和 加载时间 有效的 二进制格式编码。WebAssembly 旨在利用各种平台上可用的通用硬件功能,以本机速度执行。
WebAssembly描述了一个内存安全的沙盒执行环境,甚至可以在现有的JavaScript虚拟机中实现。当嵌入到web中时,WebAssembly将实施浏览器的同源和权限安全策略。
WebAssembly 被设计成文本格式,用于调试、测试、实验、优化、学习、教学和手工编写程序。在网上查看Wasm模块的源代码时,将使用文本格式。同时,WebAssembly 被作为网络平台的一部分,其旨在维护 Web 的无版本、经过功能测试和向后兼容的特性。WebAssembly 模块将能够调入和调出 JavaScript 上下文,并通过可从 JavaScript 访问的相同 Web APIs 访问浏览器功能。WebAssembly 还支持 非web嵌入。
本文针对 Web 前端 以及 NodeJS 或基于NodeJS 的桌面(如electron)或其它场景应用的开发人员进行讲解,假定已有 浏览器 或 NodeJS 的开发经验。
本文从零搭建一个 Rust 项目,在其中穿插讲解需要用到的一些知识,如 Rust 的 wask-pack 模块。然后在实际项目中简单将 Rust 项目编译好,分别讲述如何在 浏览器、NodeJS 中运行它。
请参考博文 《开发环境搭建与 rust 工具介绍》,文本不再赘述。
新建 Rust 项目 hello-wasm:
cargo new hello-wasm
进入该项目:
cd hello-wasm
可以看到有以下目录和文件:
在 src
目录下,有一个名为 main.rs
的文件。我们可以使用 VScode 或者 Vim 等程序编辑它,修改为我们自己的代码。
vim src/main.rs
由于我们目标是写一个用于 npm 的模块,这个自动生成的代码没有任何作用的。
然后,我们另外编辑一个 src/lib.rs
文件:
# 此处假定当前位于项目根目录
# 如果使用 VSCode,则使用命令 code src/lib.rs
vim src/lib.rs
内容如下:
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
前一节的代码中用到了 wasm_bindgen 模块,该模块用于 Rust 与 JavaScript 交互。另外还有 wasm-pack 模块用于构建 wasm,它们都需要单独在项目中安装。你可以直接使用 cargo 工具添加:
cargo add wasm-pack
cargo add wasm_bindgen
完成后,在项目配置文件中增加依赖项的记录:
关于 添加 wasm-pack 模块 更详细的方法请参考 《3.2 将 wasm-pack
模块添加到你的 Rust 项目》 小节。
然后编辑 Cargo.toml
的 lib
部分,以告诉 Rust 为我们的包建立一个 cdylib 版本。添加以下内容:
[lib]
crate-type = ["cdylib", "rlib"]
在本文对应的实操,将会用到各种工具,由于不同的人习惯不一样,尤其是某些软件在官方不发布二进制文件仅仅发布源代码时,大家习惯于使用不同的社区构建版本。在这里博主我已经为读者提前下载好了各种工具,提供这些工具安装方式的介绍,这些工具都在我的资源上传区可以找到。rust 语言自生就需要各种依赖,如:
- python 3 or 2.7
- git
- 一个C编译器 (为主机搭建时,
cc
就够了;交叉编译可能需要额外的编译器) - curl (在Windows上不需要)
- pkg-config 如果您在Linux上编译并以Linux为目标
- libiconv (已经包含在基于Debian的发行版的glibc中)
要构建Cargo,还需要OpenSSL(大多数Unix发行版上的 libssl-dev 或 openssl-devel)。如果从源代码构建LLVM,您将需要额外的工具:
这一节记录相关的一些工具是如何安装的。
Rust的MSVC版本还需要安装Visual Studio 2017(或更高版本),以便 rustc 可以使用其链接器。最简单的方法就是通过 Visual Studio 安装。
你可以访问 https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=Community&channel=Release&version=VS2022&source=VSLandingPage&passive=false&cid=2030下载 Visual Studio 安装工具,然后选择安装 Visual Studio 生成工具安装:
MinGW(Minimalist GNU on Windows)也就是 GCC 的 Windows 版本,其中GNU 编译器集合包括 C、C++、 Objective-C, Fortran, Ada、Go 和 D,以及这些语言的库 (libstdc++,…),而 GCC 最初是作为 GNU 操作系统的编译器编写的。
针对 MSVC 的 Windows 平台(例如,您的目标三端in -msvc
)要求cl.exe
,可用并在 path
环境变量中。这通常出现在标准的Visual Studio 安装中,并且可以通过运行适当的开发人员工具 shell 来设置路径。
面向 MinGW 的 Windows平台(例如-gnu中的目标三端)要求cc在 path
环境变量中可用。推荐使用 Win-builds 安装系统的 MinGW-w64 发行版。您也可以通过 MSYS2 获得它。确保安装与你的 rustc 安装相对应的适当架构。来自老 MinGW 项目的 GCC 仅与 32位 rust编译器 兼容。
你可以在 https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/mingw-w64-v11.0.0.zip/download下载 MinGW 安装管理器:
MinGW踩坑记录:安装构建rust后会提示没有 clang,其bin目录也确实没有这个文件。
然后通过它选择包完成安装。
你也可以自己在 https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/ 上下载 MinGW-w64 的不同版本:
而 MinGW-w64 官方网站的地址是:http://mingw-w64.org ,你可以在 https://sourceforge.net/projects/mingw-w64/ 寻找下载链接。
在 Windows 上安装 mingw 的另外一个方式是使用 choco 包管理工具,你需要单独安装该工具。然后:
choco install mingw
或者使用 MSYS2 ,下载会相对容易些。其官网为:https://www.msys2.org/。你也可以访问 Mingw-w64 的官网 https://www.mingw-w64.org/ 安装其它版本。
MSYS2踩坑记录:安装后会提示没有 clang,打开其目录,有一个clang64.exe和一个 clang32.exe。我尝试将它们改为 clang.exe 然后构建 rust,有弹框报错,不能处理文件。
安装完成后,将你的安装目录添加到系统的 path
环境变量中,然后运行:
msys2_shell -mingw64
以开 mingw64 窗口,在该窗口中输入以下命令:
# 更新软件包镜像(如果您全新安装了MSYS2,则可能需要)
pacman -Sy pacman-mirrors
# 安装Rust所需的构建工具。如果您正在构建32位编译器,那么请将下面的“x86_64”替换为“i686”。
# 如果您已经安装了Git、Python或CMake,并且在 PATH 中,您可以从这个列表中删除它们。
# 请注意,不要**使用“msys2”子系统中的“python2”、“cmake”和“ninja”包,这一点很重要。众所周知,使用这些包时,构建会失败。
pacman -S git \
make \
diffutils \
tar \
mingw-w64-x86_64-python \
mingw-w64-x86_64-cmake \
mingw-w64-x86_64-gcc \
mingw-w64-x86_64-ninja
这写都将安装到 mingw 的目录下,建议如果已经独立按照就不需要再安装了。
安装完成以上这些后,在你的电脑上将可以导航到你的 Rust源代码,然后这样构建它:
python x.py setup user && python x.py build && python x.py install
如果内有安装,也不想使用 pacman 命令来安装。在 Windows也可以运行 winget 工具安装:
winget install -e Python.Python.3
winget install -e Kitware.CMake
winget install -e Git.Git
然后使用 pip 工具安装:
pip install setuptools-rust
pip install cryptography
pip install paramiko
或者使用 LLVM,这个我尝试时是好用的。
在 类 Unix 平台要求 cc
是 C 编译器。例如,这可以通过在 Linux 发行版上安装 cc/clang 和在 macOS 上安装 Xcode 来找到。
在 Windows 上使用 wasm-pack
构建 WebAssembly 时,需要 OpenSSL 库。请确保你的系统上已安装 OpenSSL。
a. 下载 OpenSSL:OpenSSL 官方不以二进制形式分发包,因此你无法下载官方版本的二进制安装包。
可以先将源码下载过来:
git clone https://github.com/openssl/openssl.git
你需要参考:https://github.com/openssl/openssl/blob/master/NOTES-WINDOWS.md进行构建。
社区提供了一些构建好的二进制版本,可以在社区的页面查看:
https://wiki.openssl.org/index.php/Binaries
(或者使用我准备地这个版本:
https://download.csdn.net/download/qq_28550263/87821455)
b. 安装 OpenSSL:构建的 OpenSSL 安装程序,并按照安装向导的指示完成安装过程。
设置 OpenSSL 环境变量:如果已经安装了 OpenSSL,但
wasm-pack
无法找到它,您可以尝试手动设置 OpenSSL 的环境变量。a. 打开系统环境变量设置:在 Windows 11 上,点击 “开始” 按钮,搜索并打开 “编辑系统环境变量”。
b. 点击 “环境变量” 按钮:在 “系统属性” 窗口中,点击 “环境变量” 按钮。
c. 添加 OpenSSL 环境变量:在 “系统变量” 部分,点击 “新建” 按钮,并添加以下变量:
- 变量名:
OPENSSL_DIR
- 变量值:OpenSSL 安装目录的路径(例如:
D:\Program Files\OpenSSL
)
d. 点击 “确定” 保存设置,并关闭所有打开的窗口。
- 变量名:
重新运行
cargo install wasm-pack
:在设置完 OpenSSL 环境变量后,重新运行cargo install wasm-pack
命令,看是否仍然出现错误。这样做会将 OpenSSL 的路径信息传递给构建过程,以便成功编译和安装wasm-pack
。
如果上述步骤仍然无法解决问题,请确保您按照正确的顺序执行了上述步骤,并且 OpenSSL 的安装路径正确设置。如果问题仍然存在,请尝试使用较新版本的 OpenSSL 或 wasm-pack
,以确保软件版本的兼容性。
如果问题仍然存在,请提供更多错误信息或运行命令时使用 RUST_BACKTRACE=1
环境变量,以便我能够更详细地了解问题并提供进一步的帮助。
Win32OpenSSL 也是一个社区预构建的 Windows 二进制版本:
https://slproweb.com/products/Win32OpenSSL.html 上找到你需要的安装包版本,然后安装到指定文件夹。
接着使用 Powershell 设置环境变量(依据你的安装位置修改):
# 设置 OpenSSL-Win64 目录
[System.Environment]::SetEnvironmentVariable('OPENSSL_DIR','D:\Program Files\OpenSSL-Win64','User')
# 设置 OpenSSL-Win64 的 bin 目录
[System.Environment]::SetEnvironmentVariable('OPENSSL_LIB_DIR','D:\Program Files\OpenSSL-Win64\bin','User')
# 设置 OpenSSL-Win64 的 include 目录
[System.Environment]::SetEnvironmentVariable('OPENSSL_INCLUDE_DIR','D:\Program Files\OpenSSL-Win64\include','User')
某些模块在构建时期用到 Perl 运行时。我已经为读者朋友准备好了一个 Perl 运行时,其下载地址为:
安装完成后,需要将 Perl 的二进制文件目录添加到系统的环境变量,以方便我们和程序日后进行访问或调用 Perl 解释器:
比如我将 Strawberry 安装到 D 盘下,那么 Perl 的目录位于:D:\Strawberry\perl\bin。
在 Windows 菜单中搜索 环境变量编辑器,将其单击打开:
点击 “环境变量”:
打开系统变量的 Path 变量名,点击新建,将我们刚刚的路径新增进去,然后保存退出。
你可以使用以下命令查看是否安装成功:
perl -v
如果看到版本号等信息,说明你已经在你的计算机上成功地部署了 Perl:
【注意】:构建前你需要将
wasm-pack
的二进制目录注册到path环境变量。 windows 系统上如果一直使用的是安装到当前用户而非安装到系统, windows 系统上,wasm-pack 全局安装后,.wasm-pack
位于 当前用户目录下的 AppData(通常为隐藏目录)下的Local目录下。 比如我的系统当前用户名为a2911,则对应 C:\Users\a2911\AppData\Local.wasm-pack。其中以 wasm-bindgen-cargo-install 开头的目录及其下的 bin 目录就是我们要添加到 Path 环境目录下的。比如我这里是 C:\Users\a2911\AppData\Local.wasm-pack\wasm-bindgen-cargo-install-0.2.86\bin。
可能你对一些地方还不是很明白,不过作为快速上手,可以跟着本文先构建上面的 rust 项目为 npm 模块,这需要用到 wasm-pack CLI,可以参考 《3.3 安装 wasm-pack
的命令行工具》 进行安装。
安装后,回到本项目的根目录,使用该脚手架的 build
命令进行构建,格式如下:
wasm-pack build --target web
第一次执行这个命令会需要很长一段时间,尤其是第一次执行时,需要下载一些相关模块,需要耐心等待。如图:
一旦执行完成,可以在项目根目录下的 pkg 目录中找到为你生成的 npm模块,如图所示:
这个目录就是一个包含 xxx.wasm
、xxxx.wasm.d.ts
、xxxx.js
、xxxx.d.ts
的 一个 npm包:
wasm-pack build 将做以下几件事:
- 编译Rust:将你的 Rust 代码编译成 WebAssembly。
- 生成JS接口:在编译好的 WebAssembly 代码基础上运行 wasm-bindgen,生成一个 JavaScript 文件将 WebAssembly 文件包装成一个模块以便 npm 能够识别它。
- 移入新建
pkg
目录:创建一个 pkg 文件夹并将 JavaScript 文件和生成的 WebAssembly 代码移到其中。 - 转换项目配置文件:读取你的 Cargo.toml 并生成相应的 package.json。
- 复制 readme.md 文件:复制你的 README.md (如果有的话) 到文件夹中。
- 结果:在 pkg 文件夹下得到了一个 npm 包。
依据该模块主页对自身的描述,该工具旨在成为 构建和使用 rust 生成的 WebAssembly 的 “一站式商店”(one-stop shop),你可以在 浏览器 或 Node.js 中使用 javascript 进行交互。
wasm-pack 帮助您 构建 rust 生成的 WebAssembly 包,您可以将其发布到 npm 注册表,或者在您已经使用的工作流中与任何 JavaScript 包一起使用,如 Webpack。
和其它任意 Rust 模块一样,有两种方式添加该模块到你的项目中。第一种方式是直接使用 cargo
包管理工具:
cargo add wasm-pack
或者使用第二种方式,编辑项目的 Cargo.toml 文件,在模块依赖项处添加该行:
wasm-pack = "0.11.1"
【注意】:此项目需要 Rust 1.30.0 或更高版本。
其中右侧双引号中的是该模块的版本号,本文写作时最新的版本号为"0.11.1",读者可以指定自己尝试时的最新版本号。
wasm-pack
模块提供了一个命令行工具,你需要手动安装它。
你可以直接下载该初始化工具:
https://github.com/rustwasm/wasm-pack/releases/download/v0.11.1/wasm-pack-init.exe,这个工具仅支持 64 位系统。下载完成后运行,将显示一个命令行窗口并很快就能够完成,完成后退出即可。一旦安装完成,将可以在你的系统中使用 wasm-pack 命令。
如果你是Linux或者Linux的Windows子系统用户,请在您的终端中运行以下程序,然后按照屏幕上的说明安装wasm-pack:
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
该命令的语法格式为:
wasm-pack [FLAGS] [OPTIONS] <SUBCOMMAND>
其中,FLAGS 表示标志。提供以下标志项:
命令 | 别名 | 描述 |
---|---|---|
-h |
--help |
打印帮助信息 |
-q |
--quiet |
不输出信息到控制台 |
-V |
--version |
打印版本信息 |
-v |
--verbose |
日志详细程度基于使用的v的数量 |
其中,OPTIONS 表示选项。提供以下选项:
选项 | 描述 |
---|---|
--log-level <log-level> |
表示 wasm-pack 应记录的最大消息级别。 可能的值包括: info , warn , error 。默认值为:info 。 |
其中,SUBCOMMAND 表示子命令。提供以下子命令:
子命令 | 描述 |
---|---|
build |
🏗️ 构建您的 npm 包! |
help |
打印该消息或给定子命令的帮助 |
login |
👤 添加npm注册表用户帐户!(别名:adduser 、add-user ) |
new |
🐑 使用模板创建新项目 |
pack |
🍱 为你的 npm包 创建一个 tar,但是不要发布! |
publish |
🎆 打包你的 npm包 并发布! |
wasm-pack 模块在内部使用 env_logger 模块作为其日志器。要配置日志级别,请使用 RUST_LOG
环境变量。例如(powershell):
- 仅仅在当前窗口中有效的设置:
$env:RUST_LOG="info"
- 长期保存到当前用户的环境变量设置:
[System.Environment]::SetEnvironmentVariable('RUSTUP_LOG','info','User')
在 《3.3.3 wasm-pack CLI 的用法解析》 小节中,我们介绍了 wasm-pack 提供的脚手架,其中有一个 new
命令也是可以用来创建 Rust 项目的。现在我们使用该项目来“实操”一下:
wasm-pack new hello-wasm
该命令创建了一个名为 hello-wasm 的项目,其中包含了以下子目录和文件:
该使用 wasm-pack 创建的项目配置文件 Cargo.toml 初始内容为:
[package]
name = "hello-wasm"
version = "0.1.0"
authors = ["your_user_name <xxxxxx+xxxxx@users.noreply.github.com>"]
edition = "2018"
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies]
wasm-bindgen = "0.2.63"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.6", optional = true }
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
wee_alloc = { version = "0.4.5", optional = true }
[dev-dependencies]
wasm-bindgen-test = "0.3.13"
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"
其中默认为我们安装了 wasm-bindgen 模块,该模块用于 促进 Wasm模块 和 JavaScript之间的高级交互。
要在将 Rust 程序编译为 WebAssembly(Wasm),您可以按照以下步骤进行操作:
安装 Rust:首先,您需要安装 Rust 编程语言的工具链。您可以从 Rust 官方网站(https://www.rust-lang.org)下载并安装 Rust。
安装 wasm-pack:wasm-pack 是一个用于打包和构建 WebAssembly 的工具。您可以使用 Cargo(Rust 的包管理器)安装 wasm-pack。在命令行中运行以下命令来安装 wasm-pack:
cargo install wasm-pack
创建 Rust 项目:在命令行中,进入您的 Rust 项目的根目录,并执行以下命令创建一个新的 Rust 项目:
cargo new my_project
进入项目目录:使用
cd
命令进入新创建的项目目录:cd my_project
编写 Rust 代码:使用您喜欢的文本编辑器编写 Rust 代码。将您的 Rust 代码保存在
src
目录下的.rs
文件中。配置 Cargo.toml:在项目的根目录中,打开
Cargo.toml
文件,并添加以下内容来配置您的项目以构建为 WebAssembly:[lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2"
构建 WebAssembly:在命令行中,执行以下命令以构建 WebAssembly:
wasm-pack build --scope xxxxx --target web
这将使用 wasm-pack 将 Rust 项目构建为 WebAssembly 模块。生成的 WebAssembly 文件将位于
pkg
目录下。集成 WebAssembly 到 Web 项目:将生成的 WebAssembly 文件(
.wasm
和.js
文件)复制到您的 Web 项目中,并通过 JavaScript 脚本加载和使用 WebAssembly。
这些步骤将帮助您在 Windows 11 上将 Rust 程序编译为 WebAssembly。请注意,要成功编译为 WebAssembly,您的 Rust 代码和相关依赖库需要与 WebAssembly 目标兼容。在开发过程中,您可能还需要学习和了解 wasm-bindgen,它是一个用于在 Rust 和 JavaScript 之间进行交互的工具库。
在运行 wasm-pack build
后,生成的 pkg
目录是用于存放 WebAssembly 包(Wasm 包)及其相关文件的目录。这个目录中的文件用于在 Web 环境中使用和调用生成的 WebAssembly 模块。先前我们已经展示了该项目的结构:
这是编译生成的 WebAssembly 模块文件,其中包含了你的 Rust 代码编译后的机器码。它是使用 Rust 编写的代码的编译结果,可以在 Web 环境中加载和执行。
这是一个 TypeScript 类型定义文件,用于提供与 your_package_bg.wasm
文件交互的类型信息。它包含了与 WebAssembly 模块中导出函数的类型定义,以便在 TypeScript 代码中正确使用这些函数。
这些文件的结合使用,可以使你在 Web 环境中方便地使用 Rust 编写的 WebAssembly 模块。你可以使用 your_package.js
文件作为入口点,在你的 JavaScript 或 TypeScript 代码中调用和使用 WebAssembly 模块中的函数和对象。
比如在我们的示例中,该文件的内容为:
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
export function greet(a: number, b: number): void;
export function __wbindgen_malloc(a: number): number;
export function __wbindgen_realloc(a: number, b: number, c: number): number;
这是与 WebAssembly 模块交互的 JavaScript 模块。它提供了与 WebAssembly 模块通信的接口,包括导入和导出函数,以及其他必要的功能。该文件提供了一个高级的 JavaScript API,使得在网页中可以方便地使用 WebAssembly 模块。
比如在我们的示例中,该文件的内容为:
let wasm;
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
let cachedUint8Memory0 = null;
function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
let WASM_VECTOR_LEN = 0;
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
? function (arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
}
: function (arg, view) {
const buf = cachedTextEncoder.encode(arg);
view.set(buf);
return {
read: arg.length,
written: buf.length
};
});
function passStringToWasm0(arg, malloc, realloc) {
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
const ptr = malloc(buf.length) >>> 0;
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr;
}
let len = arg.length;
let ptr = malloc(len) >>> 0;
const mem = getUint8Memory0();
let offset = 0;
for (; offset < len; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
if (offset !== len) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3) >>> 0;
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
/**
* @param {string} name
*/
export function greet(name) {
const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
wasm.greet(ptr0, len0);
}
async function __wbg_load(module, imports) {
if (typeof Response === 'function' && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(module, imports);
} catch (e) {
if (module.headers.get('Content-Type') != 'application/wasm') {
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
} else {
throw e;
}
}
}
const bytes = await module.arrayBuffer();
return await WebAssembly.instantiate(bytes, imports);
} else {
const instance = await WebAssembly.instantiate(module, imports);
if (instance instanceof WebAssembly.Instance) {
return { instance, module };
} else {
return instance;
}
}
}
function __wbg_get_imports() {
const imports = {};
imports.wbg = {};
imports.wbg.__wbg_alert_8755b7883b6ce0ef = function(arg0, arg1) {
alert(getStringFromWasm0(arg0, arg1));
};
return imports;
}
function __wbg_init_memory(imports, maybe_memory) {
}
function __wbg_finalize_init(instance, module) {
wasm = instance.exports;
__wbg_init.__wbindgen_wasm_module = module;
cachedUint8Memory0 = null;
return wasm;
}
function initSync(module) {
if (wasm !== undefined) return wasm;
const imports = __wbg_get_imports();
__wbg_init_memory(imports);
if (!(module instanceof WebAssembly.Module)) {
module = new WebAssembly.Module(module);
}
const instance = new WebAssembly.Instance(module, imports);
return __wbg_finalize_init(instance, module);
}
async function __wbg_init(input) {
if (wasm !== undefined) return wasm;
if (typeof input === 'undefined') {
input = new URL('hello_wasm_bg.wasm', import.meta.url);
}
const imports = __wbg_get_imports();
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
input = fetch(input);
}
__wbg_init_memory(imports);
const { instance, module } = await __wbg_load(await input, imports);
return __wbg_finalize_init(instance, module);
}
export { initSync }
export default __wbg_init;
这是 TypeScript 类型定义文件,用于提供与 WebAssembly 模块交互的类型信息。它定义了与 JavaScript 模块中的函数和对象进行交互时使用的类型签名,以提供静态类型检查和类型提示的支持。
比如在我们的示例中,该文件的内容为:
/* tslint:disable */
/* eslint-disable */
/**
* @param {string} name
*/
export function greet(name: string): void;
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
export interface InitOutput {
readonly memory: WebAssembly.Memory;
readonly greet: (a: number, b: number) => void;
readonly __wbindgen_malloc: (a: number) => number;
readonly __wbindgen_realloc: (a: number, b: number, c: number) => number;
}
export type SyncInitInput = BufferSource | WebAssembly.Module;
/**
* Instantiates the given `module`, which can either be bytes or
* a precompiled `WebAssembly.Module`.
*
* @param {SyncInitInput} module
*
* @returns {InitOutput}
*/
export function initSync(module: SyncInitInput): InitOutput;
/**
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
* for everything else, calls `WebAssembly.instantiate` directly.
*
* @param {InitInput | Promise<InitInput>} module_or_path
*
* @returns {Promise<InitOutput>}
*/
export default function __wbg_init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
这里再做一些补充说明。这里的 README.md 文件是 wasm-pack 自动地帮我们复制过来地,这就意味着我们只需要再原始的 Rust 项目中写好该模块的介绍。
这个用于 NodeJS 的项目配置文件是再原始 Rsut 项目配置文件 cargo.toml 的基础上进行生成的,并与之在一些基本信息上保持一致,比如相同的版本号,等等。
- 点赞
- 收藏
- 关注作者
评论(0)