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

总结

可以运行

感觉搞麻烦了。

相关推荐
a cool fish(无名)6 小时前
rust-方法语法
开发语言·后端·rust
a cool fish(无名)21 小时前
rust-参考与借用
java·前端·rust
叶 落1 天前
[Rust 基础课程]猜数字游戏-获取用户输入并打印
rust·rust基础
RustFS1 天前
RustFS 如何修改默认密码?
rust
景天科技苑1 天前
【Rust线程池】如何构建Rust线程池、Rayon线程池用法详细解析
开发语言·后端·rust·线程池·rayon·rust线程池·rayon线程池
该用户已不存在2 天前
Zig想要取代Go和Rust,它有资格吗
前端·后端·rust
用户1774125612442 天前
不懂装懂的AI,折了程序员的阳寿
rust
量子位3 天前
vivo自研蓝河操作系统内核开源!Rust开发新机遇来了
rust·ai编程
祈澈菇凉3 天前
rust嵌入式开发零基础入门教程(六)
stm32·单片机·rust
祈澈菇凉3 天前
rust嵌入式开发零基础入门教程(二)
开发语言·后端·rust