前言
不多废话
直言的说,笔者看到这篇文章大佬的文章
【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文件中,添加插件
import {ViteRsw} from "vite-plugin-rsw";
plugins: [react(), ViteRsw()],
添加脚本
"scripts": {"dev": "vite","build": "rsw build && tsc && vite build","preview": "vite preview","tauri": "tauri","rsw": "rsw","tauri:dev": "tauri dev"},
初始化rsw项目
pnpm rsw init
pnpm rsw new src-wasm
在根目录下会创建一个rsw.toml文件
项目结构如下
修改rsw.toml的内容
[new]using = "rsw"[[crates]]
name = "src-wasm"
在新的shell中启动监听
pnpm rsw watch
可以看到目录结构
使用默认的方法
可以看到有个默认的方法greet
#[wasm_bindgen]
pub fn greet(name: &str) {alert(&format!("[rsw] Hello, {}!", name));
}
在src/App.tsc文件中
代码如下
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
先看看通信函数
#[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
#[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;}
原来是添加的外部扩展。
因此笔者使用有参数的,即
#[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"])]async fn invoke(cmd: &str, args: JsValue) -> JsValue;
如果使用官网的,需要配置全局的Tauri
"app": {"withGlobalTauri":true,...},
既然配置使用async,那还需要其他依赖,在src-warm的Cargo.toml文件中,依赖如下
[dependencies]
wasm-bindgen = "0.2.83"
serde-wasm-bindgen = "0.6.5"
wasm-bindgen-futures = "0.4.50"
serde_json="1.0.140"
修改greet函数,如下
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())
}
在前端调用
async function handleClick(){await greet("world")}
结果如下
tauri-wasm
实际上,笔者在github中发现了这个库
p1mo/tauri-wasm: wasm bindings for Tauri v2 API & Pluginshttps://github.com/p1mo/tauri-wasm可以使用,尝试一下
安装依赖
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一样
前端
import {invoke} from '@tauri/api/core'
导包类似的
use tauri_wasm::api::core::invoke;
看看这个invoke的定义
pub async fn invoke<A: Serialize, R: DeserializeOwned>(cmd: &str, args: &A) -> crate::Result<R>
args需要实现序列化,R需要实现反序列化。
因此,代码如下
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());
}
总结
可以运行
感觉搞麻烦了。