加载中...

基于 Rust 的 Wasm 开发探索与实践

基于 Rust 的 Wasm 开发探索与实践

一、参考资料

参考官方技术文档 https://rustwasm.github.io/

二、安装脚手架 cargo-generate

  1. # cargo-generate 用于快速生成 WASM 项目的脚手架(类似 create-react-app)
  2. cargo install cargo-generate

New Image

New Image

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

New Image

 双击安装之后在 Cargo 根路径下多出一个 wasm-pack.exe 

四、创建一个 WASM 项目

  1. # 使用模板生成
  2. cargo generate --git https://github.com/rustwasm/wasm-pack-template
  3. # 使用文档 GitHub - cargo-generate/cargo-generate: cargo, make me a project
  4. # templates on github
  5. cargo generate --git https://github.com/username-on-github/mytemplate.git
  6. # or just
  7. cargo generate username-on-github/mytemplate
  8. # templates on other git platforms
  9. cargo generate gl:username-on-gitlab/mytemplate
  10. cargo generate bb:username-on-bitbucket/mytemplate
  11. # this scheme is also available for github
  12. cargo generate gh:username-on-github/mytemplate
  13. # for a complete list of arguments and options
  14. cargo help generate

New Image

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

New Image

wasm-pack build --target web

New Image

New Image

五、创建一个Vue项目 

  1. # VueCli,弃用
  2. # vue create -m cnpm webdemo
  3. # 使用 Vite
  4. cnpm create vite@latest

New Image

New Image

六、引用 wasm 模块

  1. <script setup lang="ts">
  2. import { onMounted, ref } from ''vue''
  3. import init, { greet } from ''../../pkg/mydemo.js''
  4. defineProps<{ msg: string }>()
  5. const count = ref(0)
  6. onMounted(async () => {
  7. await init()
  8. greet()
  9. })

New Image

将 pkg 复制到前端根目录下。 

七、运行测试

New Image

八、 序列化与出入参

  1. > js-sys 用于将 Rust 类型 => JS 类型
  2. > wasm_bindgen 中的 JsValue 用于将 JS 类型 => Rust 类型
  1. // 示例一
  2. #[wasm_bindgen]
  3. pub extern "C" fn gen_pubKey(seed: &[u8]) -> Uint8Array {
  4. let (privKey, pubKey) = ed25519::keypair(&seed);
  5. unsafe { Uint8Array::view(&pubKey) }
  6. }
  7. // 示例二
  8. extern crate serde_json;
  9. extern crate wasm_bindgen;
  10. use wasm_bindgen::prelude::*;
  11. #[macro_use]
  12. extern crate serde_derive;
  13. #[wasm_bindgen]
  14. pub fn test(array: JsValue) {
  15. let elements: Vec<u32> = array.into_serde().unwrap();
  16. }
  17. // 示例三
  18. pub extern "C" fn greet(a: &str) -> String {
  19. format!("Hello, {}!", a)
  20. }
  21. #[export_name = "greet"]
  22. pub extern "C" fn __wasm_bindgen_generated_greet(
  23. arg0_ptr: *const u8,
  24. arg0_len: usize,
  25. ) -> *mut String {
  26. let arg0 = unsafe {
  27. let slice = ::std::slice::from_raw_parts(arg0_ptr, arg0_len);
  28. ::std::str::from_utf8_unchecked(slice)
  29. };
  30. let _ret = greet(arg0);
  31. Box::into_raw(Box::new(_ret))
  32. }
  33. // 示例四
  34. #[wasm_bindgen]
  35. pub fn get_printers() -> js_sys::Array {
  36. let list = js_sys::Array::new();
  37. let printers = printers::get_printers();
  38. for printer in printers.clone() {
  39. list.push(&js_sys::JsString::from(printer.name));
  40. }
  41. list
  42. }
  43. // 示例五
  44. extern crate serde_json;
  45. extern crate wasm_bindgen;
  46. use wasm_bindgen::prelude::*;
  47. #[macro_use]
  48. extern crate serde_derive;
  49. #[derive(Serialize, Deserialize)]
  50. pub struct Element {
  51. name: String,
  52. id: String,
  53. parent_id: String,
  54. }
  55. #[wasm_bindgen]
  56. pub fn test(js_objects: &JsValue) {
  57. let elements: Vec<Element> = js_objects.into_serde().unwrap();
  58. }

九、WASM 安全性【OS 资源访问限制】

WASM 想要执行 WindowOS 的一些脚本,抛出平台不支持异常;

New Image

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

New Image

十、Linux 开发环境搭建

Rust Wasm Linux开发环境搭建_centos安装rust_余衫马的博客-CSDN博客Linux 下 Rust + Wasm/Wasi 开发_centos安装rustNew Imagehttps://blog.csdn.net/weixin_47560078/article/details/130559636