一、参考资料
参考官方技术文档 https://rustwasm.github.io/
二、安装脚手架 cargo-generate
- # cargo-generate 用于快速生成 WASM 项目的脚手架(类似 create-react-app)
- cargo install cargo-generate


三、下载安装 wasm-pack.exe 打包工具

双击安装之后在 Cargo 根路径下多出一个 wasm-pack.exe
四、创建一个 WASM 项目
- # 使用模板生成
- cargo generate --git https://github.com/rustwasm/wasm-pack-template
-
- # 使用文档 GitHub - cargo-generate/cargo-generate: cargo, make me a project
-
- # templates on github
- cargo generate --git https://github.com/username-on-github/mytemplate.git
-
- # or just
- cargo generate username-on-github/mytemplate
-
- # templates on other git platforms
- cargo generate gl:username-on-gitlab/mytemplate
- cargo generate bb:username-on-bitbucket/mytemplate
-
- # this scheme is also available for github
- cargo generate gh:username-on-github/mytemplate
-
- # for a complete list of arguments and options
- cargo help generate

在项目目录下运行 wasm-pack build 命令,即可编译出 WASM 模块。wasm-pack 会在项目的 pkg 目录下生成 .wasm 文件和相关的 js 胶水代码。

wasm-pack build --target web


五、创建一个Vue项目
- # VueCli,弃用
- # vue create -m cnpm webdemo
- # 使用 Vite
- cnpm create vite@latest


六、引用 wasm 模块
- <script setup lang="ts">
- import { onMounted, ref } from ''vue''
-
- import init, { greet } from ''../../pkg/mydemo.js''
-
- defineProps<{ msg: string }>()
-
- const count = ref(0)
-
- onMounted(async () => {
- await init()
- greet()
- })

将 pkg 复制到前端根目录下。
七、运行测试

八、 序列化与出入参
- > js-sys 用于将 Rust 类型 => JS 类型
- > wasm_bindgen 中的 JsValue 用于将 JS 类型 => Rust 类型
- // 示例一
- #[wasm_bindgen]
- pub extern "C" fn gen_pubKey(seed: &[u8]) -> Uint8Array {
- let (privKey, pubKey) = ed25519::keypair(&seed);
- unsafe { Uint8Array::view(&pubKey) }
- }
-
- // 示例二
- extern crate serde_json;
- extern crate wasm_bindgen;
- use wasm_bindgen::prelude::*;
-
- #[macro_use]
- extern crate serde_derive;
- #[wasm_bindgen]
- pub fn test(array: JsValue) {
- let elements: Vec<u32> = array.into_serde().unwrap();
- }
-
- // 示例三
- pub extern "C" fn greet(a: &str) -> String {
- format!("Hello, {}!", a)
- }
- #[export_name = "greet"]
- pub extern "C" fn __wasm_bindgen_generated_greet(
- arg0_ptr: *const u8,
- arg0_len: usize,
- ) -> *mut String {
- let arg0 = unsafe {
- let slice = ::std::slice::from_raw_parts(arg0_ptr, arg0_len);
- ::std::str::from_utf8_unchecked(slice)
- };
- let _ret = greet(arg0);
- Box::into_raw(Box::new(_ret))
- }
-
- // 示例四
- #[wasm_bindgen]
- pub fn get_printers() -> js_sys::Array {
- let list = js_sys::Array::new();
- let printers = printers::get_printers();
- for printer in printers.clone() {
- list.push(&js_sys::JsString::from(printer.name));
- }
- list
- }
- // 示例五
- extern crate serde_json;
- extern crate wasm_bindgen;
- use wasm_bindgen::prelude::*;
- #[macro_use]
- extern crate serde_derive;
- #[derive(Serialize, Deserialize)]
- pub struct Element {
- name: String,
- id: String,
- parent_id: String,
- }
-
- #[wasm_bindgen]
- pub fn test(js_objects: &JsValue) {
- let elements: Vec<Element> = js_objects.into_serde().unwrap();
- }
九、WASM 安全性【OS 资源访问限制】
WASM 想要执行 WindowOS 的一些脚本,抛出平台不支持异常;

WASM 是运行于浏览器当中,而浏览器本身设计为没有权限访问OS资源,这是出于安全考虑。
通过设计,WebAssembly模块运行所在的环境与基础主机系统的本机功能完全隔离(或沙盒化)。这意味着默认情况下,Wasm模块被设计为仅执行纯计算。
因此,通常无法从WASM访问“ OS”级资源,例如文件描述符,网络套接字,系统时钟和随机数。但是,在许多情况下,Wasm模块需要执行的工作不仅仅是执行纯计算。它们必须与本机“ OS”功能交互。 因此一群天才们提出了使用 WASI 操作 OS 资源,并且能够独立在浏览器之外运行,下一篇文章再做一个Rust + WASI 的 DEMO。
