前言
前面在使用http插件的时候,使用了Channel提及了一个trait——CommandArg,这个trait还是很关键的。
【Tauri2】40——tauri-plugin-http-CSDN博客https://blog.csdn.net/qq_63401240/article/details/147705455?spm=1001.2014.3001.5501这篇就来看看CommandArg这个trait
从前面的文章中,可以知道,实现了这个trait,在通信函数中就可以自动获取,不需要从前端传入
比如AppHandle、Window、Webview等都可以从后端获取。
正文
看看这个trait的定义
pub trait CommandArg<'de, R: Runtime>: Sized {
fn from_command(command: CommandItem<'de, R>) -> Result<Self, InvokeError>;
}
有生命周期,泛型R,泛型约束是Runtime。
要求实现 CommandArg 的类型是 Sized 的,即在编译时大小已知。
只有一个方法from_command,这个方法的参数的类型是CommandItem
返回 Result<Self, InvokeError>
总之,实现这个trait,必须要实现from_command这个方法。
因此,简单使用一下
使用
在src-tauri/src/com.rs文件中
定义一个类型User,为User实现这个trait。代码如下,
use serde::Serialize;
use tauri::ipc::{CommandArg, CommandItem, InvokeError};
use tauri::{Runtime};
#[derive(Serialize)]
pub struct User{
pub id: u32,
pub name: String,
}
impl<'de,R:Runtime> CommandArg<'de,R> for User {
fn from_command(command: CommandItem<'de, R>) -> Result<Self, InvokeError> {
Ok(User {
id: 1,
name: "test".to_string(),
})
}
}
直接简单地返回一个User。
在通信函数中
#[command]
fn get_user(user: User)->User {
user
}
注册通信函数。前端代码调用
type User = {
id: number;
name: string;
};
async function clicked() {
let user=await invoke<User>("get_user");
console.log(user);
console.log("id 是",user.id);
console.log("name 是",user.name);
}
不需要传参。
结果如下
没问题。
这篇文章就写完了,感觉有点少。
搞复杂点
比如,可以类似于Channel,需要传入一个东西,比如id
修改代码,结果如下
fn from_command(command: CommandItem<'de, R>) -> Result<Self, InvokeError> {
let name=command.name;
let arg=command.key;
let id: String =
Deserialize::deserialize(command).map_err(|e| Error::InvalidArgs(name, arg, e))?;
let user=User::from_str(&id)
.map_err(|_| {
InvokeError::from(format!(
"User value `{id}`, expected a String id"
))});
Ok(user?)
}
笔者使用from_str这个方法,需要使用FromStr这个trait,即
use std::str::FromStr;
impl FromStr for User {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let user=User{
id: s.parse().unwrap(),
name: "6666".to_string(),
};
Ok(user)
}
}
此时,前端写法就变了
async function clicked() {
let user=await invoke<User>("get_user",{"user":"1"});
console.log(user);
console.log("id 是",user.id);
console.log("name 是",user.name);
}
需要这个参数user,而且传一个String,
如果没有,报错如下
"invalid args `user` for command `get_user`:
command get_user missing required key user"
如果不是String
"invalid args `user` for command `get_user`:
invalid type: integer `1`, expected a string"
就像是根据id查询实体。就这样吧 ,很简单。
调试from_command函数
看看里面发生了什么。随便找个地方打个断点
笔者打了两个断点,想看看command里面长什么样的
前端pnpm run dev运行,笔者后端在Rustrover中使用debug模式运行,在Rustrover中的debug模式,实际上就是使用了lldb这个调试器,
llvm/llvm-project: The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.https://github.com/llvm/llvm-project实际上,笔者下载llvm,可以使用lldb,笔者配置了环境变量
lldb target/debug/start.exe
有报错,可以运行
r
在com.rs文件中26行设置断点
breakpoint set --file com.rs --line 26
结果如下,效果不是很好
没有rust插件,笔者lldb-rust也用不了,因为架构的原因。
因此,笔者使用RustRover中的debug模式。至于为什么RustRover中能使用,笔者也不理解。
看看command
有五个字段,plugin是None,name是&str,显而易见就是通信函数的名字——get_user
key就是其中参数的名字——user
acl笔者发现里面没有什么东西,说白了,没有初始化
长度是140698947526855,一看这个长度就不对劲,往里面看
其中pointer是NULL,因此,没有初始化。
message就比较多了
因此,笔者留到下一篇介绍,这里面有许多东西,先不慌。
走到下一个断点
看看 name
p name
不用看都可以知道,就是get_user这个字符串
结果如下
(lldb) p name
(ref$<str$>) name = {
data_ptr = 0x00007ff703d25678
length = 8
}
(lldb) memory read 0x00007ff703d25678 -c 8
0x7ff703d25678: 67 65 74 5f 75 73 65 72 get_user
没问题。
看看arg
(lldb) p arg
(ref$<str$>) arg = {
data_ptr = 0x00007ff703d25680
length = 4
}
(lldb) memory read 0x00007ff703d25680 -c 4
0x7ff703d25680: 75 73 65 72 user
没问题
按F8,步过,一直到id出现
(lldb) p id
(alloc::string::String) id = {
vec = {
buf = {
inner = {
ptr = {
pointer = {
pointer = 0x000001828380cb10
}
_marker = {}
}
cap = (__0 = 1)
alloc = {}
}
_marker = {}
}
len = 1
}
}
有地址,有长度
(lldb) memory read -c 1 0x000001828380cb10
0x1828380cb10: 31 1
结果为1 ,没问题
看看user
往前走,一直到user出现
(lldb) p user
(core::result::Result<start::com::User,tauri::ipc::InvokeError>::Ok) user = {
0 = {
id = 1
name = {
vec = {
buf = {
inner = {
ptr = {
pointer = {
pointer = 0x000002f6c9bf7d30
}
_marker = {}
}
cap = (__0 = 4)
alloc = {}
}
_marker = {}
}
len = 4
}
}
}
}
id为1,name有地址,有长度
(lldb) memory read -c 4 0x000002f6c9bf7d30
0x2f6c9bf7d30: 36 36 36 36 6666
没问题
总结
对于CommandArg 具体怎么使用,看个人需求