【Rust 实战】Rust 与 Wasm

简介: 【Rust 实战】Rust 与 Wasm

0x00 开篇


这篇文章拖欠大家好久了,现在终于来了哈哈。本篇文章将介绍使用 Rust 来编译 Wasm 。另外,本篇文章还将告诉你为什么要选择 Rust 而不是 C++,Python 呢?如果你想提升Web的性能,又或者是想用JavaScript,Typescript以外的编程语言来编写前端,那么我建议你阅读本文章。


0x01 什么是Wasm?


Wasm 是 WebAssembly 的缩写。WebAssembly 是基于栈式虚拟机的二进制指令集,可以作为编程语言的编译目标,最初是在 _Web_上使用的,但由于它的特性及开放规范,目前它可以在很多场景下使用,比如:Node.js ,嵌入式程序等。目前大约有 40+ 的语言可以编写 Wasm。


0x02 Wasm 与 Web


目前我们常用的浏览器都可以运行 Wasm。那我们为什么要在 Web 上使用 Wasm 呢?

  • 提升 Web 的性能

Wasm 是一种很容易解析的格式,它的目标就是充分发挥硬件的能力以达到原生执行效率。与 JavaScript 相比,使用 **Wasm **编写的程序可以拥有更好的性能。

  • 方便移植

如果现有的软件是使用 C 或者是 C++ 等语言编写的,可以很方便的将编译为 Wasm,移植到 Web 端。

  • 额外增加了 Web 端技能

如果你不会 JavaScript,依然可以使用其它可以编译成 Wasm 的语言来开发 Web 端,额外为自己增加了一项技能。类似的框架有 Yew,感兴趣的可以了解下。


0x03 为什么选择 Rust?


Rust 内存效率高,没有运行时,没有垃圾回收器。并且 Rust 的可靠性也很高,在编译时期可以确保大部分的内存和线程安全。与其他高级语言相比,Rust 中的编程虽然更加复杂,但是 Rust 是一种系统级编程语言,我们性能和复杂性不可兼得,只能在保证性能的同时忽略其复杂性。当然,又有人会问为什么不选择 C 或者 C++ 呢?C 或者 C++ 也同样可以实现上面的性能。最重要的原因也是我上面所说到的,C 和 C++ 没有保证内存和线程的安全,一旦发生内存级别的错误,调试起来非常痛苦,这无疑是增加了维护成本。另外像 Python 等高级语言的缺点也很明显,在性能方面很难达到合格的标准。


0x04 实战演练


PS:演示没有选择使用命令创建项目,接下来的演示将以 Windows 11 操作系统 x64 和 CLion 2022.2 版本进行演示。演示过程没有采用 CLion 的 WebAssembly 模板。


1 创建项目


创建项目时选择 Libray 模板,并删除模板创建 lib.rs的所有代码


0a2653c851af460fa595bd959398a8f1.png2d65d23f6d4748949b924e4057485923.png


2 编写代码


写一个简单的代码,计算两个整数的和。首先我们配置下 Cargo.toml。在 lib 标签下添加构建类型为 cdylib。添加 wasm-bindgen 依赖,该依赖是生成 wasm 的关键依赖。

[package]
name = "rust_wasm"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.82"

lib.rs 中编写代码

use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn sum(a: i32, b: i32) -> i32 {
    return a + b;
}


3 编译代码


下载编译工具 wasm-pack。文末附下载地址。

然后使用下面的命令编译代码,下面这行代码首次执行,当执行到 **Installing wasm-bindgen...**时会等很久,大约5-10分钟左右。

wasm-pack build --target web

PS:如果5-10分钟后,编译还卡在 Installing wasm-bindgen... 。有两种解决办法,挂梯子或者更换 Cargo 源为国内源。

以 Windows 为例,找到 Cargo 默认的安装位置 C:\Users\你自己的用户名\.cargo,如果目录下存在名为 config 的文件就直接打开,如果没有就创建一个新的 config 文件。输入以下内容并保存。

6de278e6d6694ce5bb08e7e842b7e74b.png

[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = 'ustc'
[source.ustc]
registry = "http://mirrors.ustc.edu.cn/crates.io-index"

成功安装 wasm-bindgen后,你可能还会遇到这个 warning。

warning: be sure to add `C:\Users\xxx\AppData\Local\.wasm-pack\.wasm-bindgen-cargo-install-0.2.82\bin` to your PATH to be able to run the installed binaries

我们按照提示将上面的路径添加到环境变量里,重新编译就可以了。如果编译成功,在项目目录下会生成 pkg 文件夹,里面的内容就是生成的 wasm 相关文件了。

8ec4f2997fb246878c34ecd6d122b7c6.png

主要有四个重要的文件——rust_wasm.jsrust_wasm_bg.wasmrust_wasm_bg.d.tsrust_wasm.d.ts

rust_wasm.jsrust_wasm_bg.wasm 就是我们所需的 wasm 和 js 的胶水代码。

rust_wasm_bg.d.tsrust_wasm.d.ts 则是 Typescript 类型的定义。


4 测试代码


我们写一个简单的 html 文件测试下 wasm 模块。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Rust Wasm 测试</title>
</head>
<script type="module">
    import init, {sum} from "./pkg/rust_wasm.js";
    init().then(() => {
        var result = sum(5, 6);
        document.write("wasm sum 5 + 6 = " + result)
        console.log(result);
    });
</script>
<body>
</body>
</html>

我们直接打开浏览器运行会报跨域的错误。我们要么把文件拷到服务器上,要么就在本地跑一个服务器。测试结果如下:

12c3b7f3f8814309a195c64f051d4445.png


0x05 小结


上面讲到编译过程中会卡住的问题,我感觉理论上可以本地安装wasm-bindgen和wasm-pack这俩工具,但是我并没有尝试,喜欢折腾的小伙伴可以尝试下。Rust 编译为 Wasm 的教程到这里基本就结束了。当然这也仅仅是简单的生成 Wasm。当然如果你感兴趣,我会找时间再来说下 Rust 与 JavaScript 的交互以及如何操作 DOM。另外,其实很多我们熟知的公司也都在使用 Rust 生成的 wasm,比如迪士尼的流媒体服务和亚马逊的流媒体服务等等。


0x06 其它资料


wasm-pack:https://rustwasm.github.io/

wasm-bindgen:https://github.com/rustwasm/wasm-bindgen

相关文章
|
存储 Rust 前端开发
给 Web 前端工程师看的用 Rust 开发 wasm 组件实战
wasm 全称 WebAssembly,是通过虚拟机的方式,可以在服务端、客户端如浏览器等环境执行的二进制程序。它有速度快、效率高、可移植的特点
201 0
|
7天前
|
Rust 编译器 开发者
Rust宏之derive的设计及实战
【10月更文挑战第18天】在 Rust 中,`derive` 宏是一种自动生成代码的工具,可为结构体和枚举类型自动实现特定 trait,减少重复代码。它通过语法糖简化代码,支持 Debug、Clone、PartialEq 等 trait 的自动实现,并允许开发者自定义 `derive` 宏以扩展功能。
|
28天前
|
JSON Rust 安全
30天拿下Rust之实战Web Server
30天拿下Rust之实战Web Server
39 7
|
4月前
|
Rust 图形学
【unity实战】使用unity制作一个类似Rust的3D生存建造建筑系统,具有很好的吸附性(附项目源码)
【unity实战】使用unity制作一个类似Rust的3D生存建造建筑系统,具有很好的吸附性(附项目源码)
101 1
|
Rust Linux Windows
【RUST 实战】交叉编译之Windows To Linux
【RUST 实战】交叉编译之Windows To Linux
3057 1
【RUST 实战】交叉编译之Windows To Linux
|
JSON Rust API
【Rust 实战】抖音短视频解析工具
【Rust 实战】抖音短视频解析工具
2646 0
【Rust 实战】抖音短视频解析工具
|
Rust 前端开发 JavaScript
【Rust 实战】Rust GUI 框架—抖音短视频解析工具GUI
【Rust 实战】Rust GUI 框架—抖音短视频解析工具GUI
2691 0
【Rust 实战】Rust GUI 框架—抖音短视频解析工具GUI
|
Rust JavaScript 前端开发
【Rust 实战】Rust 与 Wasm (2) —— 操作 Dom
【Rust 实战】Rust 与 Wasm (2) —— 操作 Dom
【Rust 实战】Rust 与 Wasm (2) —— 操作 Dom
|
Rust 测试技术 API
【Rust 实战】Rust与C#交互-生成DLL库
【Rust 实战】Rust与C#交互-生成DLL库
1156 0
【Rust 实战】Rust与C#交互-生成DLL库
|
Rust C++ Windows
【Rust 实战】注册表之自定义Windows11任务栏位置(上)
【Rust 实战】注册表之自定义Windows11任务栏位置(上)
【Rust 实战】注册表之自定义Windows11任务栏位置(上)