【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());
}

总结

可以运行

感觉搞麻烦了。

相关推荐
Albart57517 小时前
【玩转 AtomCode】替代Claude Code!开源多模型免费AI编码Agent深度实测教程
人工智能·rust·开源·atomcode·多模型ai
特立独行的猫A17 小时前
Rust+Tauri 2实现个人聚藏APP:一个 “注定上不了“ 的个人收藏夹
rust
jeffwang17 小时前
我把同一个压测做错了三次,第四次才发现真正的瓶颈
分布式·性能优化·rust
程序员爱钓鱼18 小时前
Rust 生命周期详解:生命周期标注、约束与真实项目应用
后端·面试·rust
MoonBit月兔18 小时前
MoonBit 受邀亮相 SPLASH/ISSTA 2026,与 Java、Rust、Eiffel、D 语言核心贡献者同场交流
开发语言·后端·rust
今天AI了吗18 小时前
Python vs Rust AI 服务基准测试全景:FastAPI、Axum、Actix-Web 的延迟与吞吐
人工智能·python·rust
Source.Liu19 小时前
【A11】项目架构设计笔记
rust
x-cmd19 小时前
用 Rust 打造 AI 时代的 SQL:把重复任务变成可执行文件
数据库·人工智能·sql·ai·容器·rust·workflow
铅笔侠_小龙虾2 天前
rust 学习(9):结构体
开发语言·学习·rust
铅笔侠_小龙虾2 天前
rust 学习(12):常用集合(上)-- Vec
rust