【Tauri2】026——Tauri+Webassembly

前言

不多废话

直言的说,笔者看到这篇文章大佬的文章

【04】Tauri 入门篇 - 集成 WebAssembly - 知乎https://zhuanlan.zhihu.com/p/533025312尝试集成一下WebAssembly,直接开始

正文

准备工作

新建一个项目

安装 vite的rsw插件和rsw

复制代码
pnpm install -D vite-plugin-rsw

cargo install rsw

配置在vite.config.ts文件中,添加插件

TypeScript 复制代码
import {ViteRsw} from "vite-plugin-rsw";
plugins: [react(), ViteRsw()],

添加脚本

TypeScript 复制代码
  "scripts": {
    "dev": "vite",
    "build": "rsw build && tsc && vite build",
    "preview": "vite preview",
    "tauri": "tauri",
    "rsw": "rsw",
    "tauri:dev": "tauri dev"
  },

初始化rsw项目

rust 复制代码
pnpm rsw init
pnpm rsw new src-wasm

在根目录下会创建一个rsw.toml文件

项目结构如下

修改rsw.toml的内容

复制代码
[new]

using = "rsw"

[[crates]]
name = "src-wasm"

在新的shell中启动监听

rust 复制代码
pnpm rsw watch

可以看到目录结构

使用默认的方法

可以看到有个默认的方法greet

rust 复制代码
#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("[rsw] Hello, {}!", name));
}

在src/App.tsc文件中

代码如下

TypeScript 复制代码
import "./App.css";
import init, { greet } from '../src-wasm/pkg/src_wasm'
import {useEffect} from "react";

function App() {
    useEffect(() => {
        init();
    }, [])
    function handleClick(){
        greet("world")
    }

    return (
        <>
            <header className="header">
                <h1>Welcome to Tauri + React</h1>
            </header>
            <main className="container">
                <button onClick={handleClick}>确定</button>
            </main>

        </>
    );
}

export default App;

启动项目,点击按钮

没问题

使用invoke

先看看通信函数

rust 复制代码
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

在大佬的文章中,没有解释怎么和tauri连用。

从官网中可以找到和wasm一起使用的东西

Calling Rust from the Frontend | Taurihttps://v2.tauri.app/develop/calling-rust/#wasm

TypeScript 复制代码
#[wasm_bindgen]
extern "C" {

    #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"], js_name = invoke)]
    async fn invoke_without_args(cmd: &str) -> JsValue;

    // invoke with arguments (default)
    #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"])]
    async fn invoke(cmd: &str, args: JsValue) -> JsValue;

 
}

原来是添加的外部扩展。

因此笔者使用有参数的,即

TypeScript 复制代码
    #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"])]
    async fn invoke(cmd: &str, args: JsValue) -> JsValue;

如果使用官网的,需要配置全局的Tauri

TypeScript 复制代码
 "app": {
    "withGlobalTauri":true,
       ...
  },

既然配置使用async,那还需要其他依赖,在src-warm的Cargo.toml文件中,依赖如下

TypeScript 复制代码
[dependencies]
wasm-bindgen = "0.2.83"
serde-wasm-bindgen = "0.6.5"
wasm-bindgen-futures = "0.4.50"
serde_json="1.0.140"

修改greet函数,如下

rust 复制代码
use serde_wasm_bindgen::to_value;
#[wasm_bindgen]
pub async fn greet(name: &str) {
    let name = to_value(&serde_json::json!({"name": name})).unwrap();
    let res = invoke("greet",name ).await;
    alert(res.as_string().unwrap().as_str())
}

在前端调用

rust 复制代码
    async function handleClick(){
        await greet("world")
    }

结果如下

tauri-wasm

实际上,笔者在github中发现了这个库

p1mo/tauri-wasm: wasm bindings for Tauri v2 API & Pluginshttps://github.com/p1mo/tauri-wasm可以使用,尝试一下

安装依赖

rust 复制代码
tauri-wasm = { git = "https://github.com/p1mo/tauri-wasm", features = [
    "all", # for all api bindings
    "plugin-all" # for all plugin bindings. should you do this? no.
] }

使用invoke

就像前端使用invoke一样

前端

TypeScript 复制代码
import {invoke} from '@tauri/api/core'

导包类似的

rust 复制代码
use tauri_wasm::api::core::invoke;

看看这个invoke的定义

TypeScript 复制代码
pub async fn invoke<A: Serialize, R: DeserializeOwned>
        (cmd: &str, args: &A) -> crate::Result<R>

args需要实现序列化,R需要实现反序列化。

因此,代码如下

rust 复制代码
use serde::{Deserialize, Serialize};
use tauri_wasm::api::core::invoke;
use wasm_bindgen::prelude::wasm_bindgen;
use tauri_wasm::js::console;
use tauri_wasm::api::app::{get_name,get_version};


#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

#[derive(Serialize)]
struct Args {
    pub name: String,
}
#[derive(Deserialize)]
struct Response {
    pub message: String,
}
#[wasm_bindgen]
pub async fn greet(name: &str){
    console::log(&format!("Hello, {}!", name));
    console::log(&format!("name is {}!", get_name().await.unwrap()));
    console::log(&format!("version is {}!", get_version().await.unwrap()));

    let args =Args {
        name: name.to_string(),
    };
    let response=invoke("greet", &args).await.unwrap();
    let res=serde_json::from_value::<String>(response).unwrap();
    alert(res.as_str());
}

总结

可以运行

感觉搞麻烦了。

相关推荐
Hello.Reader10 小时前
给你的 Rust 通用库“插上” WebAssembly 的翅膀
javascript·rust·wasm
苏近之11 小时前
一文了解 Rust 中的 Cell 和内部可变性
rust
yezipi耶不耶2 天前
Rust学习之实现命令行小工具minigrep(二)
开发语言·学习·rust
hboot2 天前
rust 全栈应用框架dioxus
前端·rust·全栈
muyouking113 天前
0.深入探秘 Rust Web 框架 Axum
开发语言·前端·rust
勇敢牛牛_3 天前
【Rust基础】使用Rocket构建基于SSE的流式回复
开发语言·后端·rust
muyouking113 天前
3.Rust + Axum 提取器模式深度剖析
前端·rust·github
pumpkin845143 天前
学习笔记十六——Rust Monad从头学
笔记·学习·rust
Hello.Reader3 天前
快速启动 Rust + WebAssembly 项目
开发语言·rust·wasm