【Day3】Tauri v2を試しに動かしてみよう【QAC24】


# ついに実行の時...！

何も悪いことは言わないので、`pnpm tauri dev`と打ってみましょう。

Vite が起動した後、Rust のコンパイルが始まります。
初回の Rust のコンパイルは絶対時間がかかるので、気長に待ちましょう。

気長に（私の環境だと、大体 3 分ぐらい）待ってると...！？

![スクリーンショット 2024-11-23 141859.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/1eb4cda6-77b8-448a-71d3-c0da722e3ab1.png)

うおおおお！！！！（歓喜！歓喜！）
なんか GUI が出てきたぞ～～！！！！

以上。

## もう少しだけ触ってみるか...

`Enter a name...`となってるところに名前を入れましょう。

![スクリーンショット 2024-11-23 142744.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/9cc9af26-5d1d-819d-b416-731858d2bd10.png)

こんな感じですか？

んで、`Greet`を押すと...

![スクリーンショット 2024-11-23 142756.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/c2b3e1f3-8e72-8af3-3f96-3bccfc351fe0.png)

おお。名前で呼んでくれた～！
これこれ。スタバのモバイルオーダーの時の嬉しさよな。

# 構造を見てみよう

ここからは VSCode なり、適当なエディターで構造を見ていきます。
エディターでプロジェクトフォルダを見ておきましょう。

沢山フォルダがあると思いますが、2 種類に分けられます。
`src`フォルダと`index.html`ファイルがフロントエンドの部分で、`src-tauri`フォルダがバックエンドの部分です。

## フロントエンド

試しに`index.html`を開いてみて...大事なところは`form`タグの中ですね。

```html
<form class="row" id="greet-form">
  <input id="greet-input" placeholder="Enter a name..." />
  <button type="submit">Greet</button>
</form>
```

ここが先ほどの名前を入れたら挨拶してくれる部分ですね。
`<input>`で名前を受け入れて、`<button>`を押したら挨拶してくれる～...という感じですね。

じゃあ実際にどのようにその挨拶が行われているのでしょうか？

## フロントエンドとバックエンドの橋渡し！

`src`フォルダの中に`main.ts`というファイルがあります。
このファイルが、`index.html`を制御している TypeScript ファイルです。

```typescript
import { invoke } from "@tauri-apps/api/core";
```

1 行目にこんなものがありますが...
`@taur-apps/api/core`の中から`invoke`というのを import しています。
(Python で読み替えたら`from tauri-apps.api.core import invoke`みたいな感じ...)

`invoke`は、バックエンドの Rust の関数を呼び出すための関数です。
第 1 引数に呼び出したい関数名を入れ、第 2 引数には呼び出す関数に渡す引数を入れます。

サンプルで書かれてるコードはこんな感じですね。

```typescript
let greetInputEl: HTMLInputElement | null;
let greetMsgEl: HTMLElement | null;

async function greet() {
  if (greetMsgEl && greetInputEl) {
    // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
    greetMsgEl.textContent = await invoke("greet", {
      name: greetInputEl.value,
    });
  }
}

window.addEventListener("DOMContentLoaded", () => {
  greetInputEl = document.querySelector("#greet-input");
  greetMsgEl = document.querySelector("#greet-msg");
  document.querySelector("#greet-form")?.addEventListener("submit", (e) => {
    e.preventDefault();
    greet();
  });
});
```

TypeScript や DOM 操作に対する知識がないと、容易には理解できないかもしれませんが、簡単な説明だけしておきますと...

最初の`let (変数名): (型);`は、変数を宣言しています。
TypeScript は Python と異なり、変数宣言時に`var`や`let`、`const`を使い、その変数の仕様を明示する必要があります。

ここについては以下の記事が参考になるかと思いますので、興味があれば読んでみてください。

https://qiita.com/cheez921/items/7b57835cb76e70dd0fc4

型については、`HTMLInputElement`や`HTMLElement`は、それぞれ`<input>`や`<div>`などの HTML 要素を表す型です。
`| null`は、その変数が`null`を許容することを示しています。

`async function greet()`は、`greet`という関数を宣言しています。
この関数が、ボタンを押したときに呼ばれる中身で、`invoke`を使ってバックエンドの関数 `greet` を呼び出しています。
`async`は、非同期関数であることを示しています。
非同期関数については後の方の記事でなんとなく解説します多分...
Python よりは簡単だと思います。

## バックエンド

んでさっきからバックエンドバックエンドゆーてるバックエンドってのはなんじゃいっていうお話ですが、`src-tauri/src/lib.rs`がバックエンドの部分です。

```rust
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}
```

これがさっきの`invoke`で呼び出していた`greet`関数です。

Rust を見たことがない人にとってはなんか難しそうな感じしますが、これも簡単に説明します。

`#[tauri::command]`は、マクロと呼ばれるもの一種「手続き型マクロ」というものです。
まずマクロというのが、簡単に言ってしまえばコードを生成するためのものです...多分。
なんとなく C 言語の`#define`に似た匂いがします。
特に手続き型マクロは、Python のデコレーターになんとなく似てるかもしれません。
Python で DiscordBOT を作ったことがあるあなたなら「なんとなく`@commands.Command`をつければ動く」を知ってるでしょう。それだよそれ。

`fn greet(name: &str) -> String`は、`greet`という関数を宣言しています。
Rust では、`fn (関数名)(引数: 引数の型) -> 戻り値の型`という形式で関数を宣言します。

`&str`というものは、文字列スライスと呼ばれているもので、そのまんま文字のスライスです。
`String`は、文字列そのものを表す型で、実際には文字の配列だったと思います。

え？何が違うの？スライス？配列？
と思ったかもしれません。

Python 的な考えで言うならスライスも配列も同じだろう多分、と。
配列は、コンパイル時に長さが決まっているもので、スライスは長さが決まっていないものです。

んでまぁ、この関数は`&str`を受け取って、`String`を返す関数です。
...が、`return`みたいなのがありませんね...？

Rust は、C 言語や TypeScript と同じように、関数の最後にはセミコロンをつける必要があります。
が！ Rust ではセミコロンをつけなくてもいい場合があります。
それが、関数の`return`として使用する場合（正確には`式`と`文`の違い）です。
その値を、その値を内包する関数の戻り値として返したいのあれでば、わざわざ`return`を使わずとも、その値をセミコロン抜きで書けばいいのです。

なんで、こんな関数でも成立します。

```rust
fn prime_number() -> i32 {
    57
}
```

この関数は、セミコロンがない 57 が中にあるので、57 を返すだけの関数です。

話を戻しますが、`format!`というのは、文字列をフォーマットするマクロです。
うわ！またマクロだ！

Python の f-string とかテンプレートリテラルのように、文字列の中に変数を埋め込むことができるやつです。
ねっ？　簡単でしょ？

# まとめ......ない

というわけで実際に動かすことが出来ました...！
暇ならいろいろいじってみてください！

明日からは全てを無に帰させて、新しいものを作ります。

Rustは当分の間出てきません。悲しいね。