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

总结

可以运行

感觉搞麻烦了。

相关推荐
Source.Liu3 小时前
【typenum】 1 说明文件(README.md)
rust
蜗牛沐雨9 小时前
Rust 中的 Pin 和 Unpin:内存安全与异步编程的守护者
服务器·开发语言·rust
hrrrrb14 小时前
【Rust】枚举和模式匹配
开发语言·rust
zhuziheniaoer18 小时前
rust-candle学习笔记12-实现因果注意力
笔记·学习·自然语言处理·rust
无名之逆18 小时前
Hyperlane: Unleash the Power of Rust for High-Performance Web Services
java·开发语言·前端·后端·http·rust·web
Source.Liu18 小时前
【typenum】 0 配置文件(Cargo.toml)
rust
明月看潮生1 天前
青少年编程与数学 02-019 Rust 编程基础 01课题、环境准备
开发语言·青少年编程·rust·编程与数学
液态不合群2 天前
rust程序静态编译的两种方法总结
开发语言·后端·rust
明月看潮生3 天前
青少年编程与数学 02-019 Rust 编程基础 02课题、开始编程
开发语言·算法·青少年编程·rust·编程与数学
rayylee3 天前
Ubuntu也开始锈化了?Ubuntu 计划在 25.10 版本开始引入 Rust Coreutils
linux·ubuntu·rust