前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >tauri学习(3)-前端调用Rust代码

tauri学习(3)-前端调用Rust代码

作者头像
菩提树下的杨过
发布2022-08-23 16:05:31
1.6K0
发布2022-08-23 16:05:31
举报

上节继续,今天研究tauri中,前端如何调用Rust代码。

一、无返回值&无传参

main.rs中加1个hello方法:

然后在main方法中,参考下图暴露hello1:

Rust代码准备好之后,前端(假设是react框架)就能调用了:

import { invoke } from "@tauri-apps/api/tauri"

先引入invoke方法,然后在需要的地方:

运行效果:

二、有传参

/**
 * 可传参
 */
#[tauri::command]
fn hello2(msg: String) {
  println!("hello-2 {}!", msg);
}

多个方法暴露,参考下图:

前端调用:

<button onClick={() => invoke('hello2', { msg: "jimmy" })}>hello2</button>

三、有传参&有返回值

/**
 * 有传参,带返回值
 */
#[tauri::command]
fn hello3(msg: String) -> String {
  format!("hello-3 {}", msg)
}

前端调用:

  let hello3 = (message: String) => {
    invoke("hello3", { msg: message }).then((message) => console.log(message))
  }

四、返回复杂对象

use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize)]
struct Person {
  name: String,
  age: i32,
}

/**
 * 返回复杂对象
 */
#[tauri::command]
fn get_person(name: String, age: i32) -> Result<Person, String> {
  Ok(Person { name, age })
}

前端调用:

let get_person = (name: String, age: Number) => {
  invoke("get_person", { name, age }).then((person) => console.log(person))
}

五、性能测试

很多功能,既然原生js与rust都能实现,谁的性能更高?

还是用经典的fibonacci做为示例:

/**
 * 测试性能
 */
#[tauri::command]
fn fibonacci(n: i32) -> i32 {
  if n <= 1 {
    1
  } else {
    fibonacci(n - 1) + fibonacci(n - 2)
  }
}

前端:

// js原生版的fibonacci (by:菩提树下的杨过 http://yjmyzz.cnblogs.com)
function fibonacci_js(n: number): number {
  if (n <= 1) {
    return 1;
  }
  return fibonacci_js(n - 2) + fibonacci_js(n - 1);
}

function App() {

  //js版fibonacci测试
  let js_test = (n: number) => {
    let begin = new Date().getTime();
    let result = fibonacci_js(n);
    let end = new Date().getTime();
    console.log(`fibonacci_js(${n})\t= ${result},\t执行时间: ${end - begin} ms`);
  }


  //rust版fibonacci测试
  let tauri_test = (n: number) => {
    let begin = new Date().getTime();
    invoke('fibonacci', { n }).then((result) => {
      let end = new Date().getTime();
      console.log(`fibonacci_tauri(${n})\t= ${result},\t执行时间: ${end - begin} ms`);
    });
  }
  
  ...

          <button onClick={() => js_test(38)}>fibonacci_js</button>
          <button onClick={() => tauri_test(38)}>fibonacci_tauri</button>
  ...

}

从输出耗时看,同样的硬件条件情况下,rust的实现,性能高于原生js,但略逊于wasm版本(可参见react+rust+webAssembly(wasm)示例 )

六、异常处理

Rust代码:

/**
 * 异常处理
 */
#[tauri::command]
fn is_valid_age(age: i32) -> Result<String, String> {
  if age > 0 && age < 150 {
    Ok("pass".into())
  } else {
    Err(format!("age:{} invalid", age))
  }
}

前端调用:

  let is_valid_age = (age: Number) => {
    invoke("is_valid_age", { age })
      .then((msg) => console.log(msg))
      .catch((err) => console.error(err))
  }

七、Rust异步处理

/**
 * 异步方法
 */
#[tauri::command]
async fn method_1() -> String {
  println!("method_1 is called");
  //内部再调用另1个异步方法
  let result = method_2();
  //这里不会block,会继续执行下一句
  println!("do another thing in method_1");
  //这里会阻塞,直到method_2返回
  let result = result.await;
  println!("method_2 result:{} from method_1", result);
  //返回method_2的结果 
  result
}

async fn method_2() -> String {
  println!("method_2 is called");
  //刻意停3秒【注:必须先use std::{thread, time};】
  thread::sleep(time::Duration::from_secs(3));
  format!("method_2 result")
}

前端调用时,并无特别之处,仍按promise的套路处理:

  let async_test = () => {
    invoke("method_1").then((result) => {
      console.log("result:", result
      );
    })
  }

Rust终端输出结果:

method_1 is called
do another thing in method_1
method_2 is called
method_2 result:method_2 result from method_1

八、访问tauri应用的window对象

#[tauri::command]
async fn get_window_label(window: tauri::Window) {
  println!(
    "Window: {},is_fullscreen:{:?}",
    window.label(), //获取应用窗口的label
    window.is_fullscreen() //获取应用是否全屏
  );
}

九、state管理

注:这里的state可不是react组件的state,而是指tauri应用内部的状态,比如应用查询数据库前,要先判断下db的连接状态是否正常,就可以用上这个

struct DatabaseState {
  connnted: bool,
}

fn connect_db() -> DatabaseState {
  DatabaseState { connnted: true }
}

#[tauri::command]
fn query_data(state: tauri::State<DatabaseState>) {
  assert_eq!(state.connnted, true);
  println!("query data success")
}

这里我们定义了一个DatabaseState,然后在connect_db方法里,模拟连接上db后,将connected状态置成true,然后在query_data方法中,先判断db是否连上了。

在main方法中,就可以管理状态:

参考文章:

https://tauri.app/v1/guides/features/command

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档