Rustの巻
所有権
値の所有者は基本的に1つのみ
変数の代入は基本的に所有者が移動する
なお、コピートレイが実装されている場合はコピーされる
(boolやi32など)の値はサイズが固定でスタックに積まれてコピーコストが低いから
その理由は、整数のようなコンパイル時に既知のサイズを持つ型は、スタック上にすっぽり保持されるので、 実際の値をコピーするのも高速だからです。これは、変数yを生成した後にもxを無効化したくなる理由がないことを意味します。
実際にコピーされる例
code:rust
let hoge = "hoge"; // "hoge" はスライスでコンパイル時にサイズが確定するため、スタックに積まれる
let fuga = hoge; // そのため、コピーされる
println!("{:p}", &hoge); // 0x16fd3e8d8
println!("{:p}", &fuga); // 0x16fd3e8e8
ヒープに積まれる値、かつコピートレイがない場合は所有権が移動する
code:rust
let hoge = String::from("hoge");
let _a = hoge;
println!("{}", hoge); // value borrowed here after move
関数も所有権が移動する(関数による)
code:rust
fn main() {
let hoge = String::from("hoge");
movable(hoge);
println!("{}", hoge); // value borrowed here after move
}
fn movable(s: String) {
println!("{}", s)
}
参照
まとめ
可変参照は1つまで
不変参照は何個もOK
可変と不変参照のライフタイムが被っていなければOK
所有権を移動させず、参照だけしたい場合は&で参照を渡せる
code:rust
fn main() {
let hoge = String::from("hoge");
not_move(&hoge); // 参照を渡す
println!("{}", hoge);
}
fn not_move(s: &String) {
println!("{}", s)
}
複数参照が可能
値が不変のため、複数箇所から参照されるのは問題が起きない
code:rust
let s = String::from("hoge");
let s1 = &s;
let s2 = &s;
println!("{} {} {}", s, s1, s2);
ただ、所有権を移動せず参照先の値を書き換えたい場合は可変参照を使用する
code:rust
fn main() {
let mut s = String::from("hello");
change(&mut s); // 渡す側は変数名の前に &mut をつける
println!("{}", s); // hello world
}
fn change(s: &mut String) { // 受け取る側は型の前に &mut をつける
s.push_str(" world");
}
なお、可変参照は同時に一つのみ存在できる
他の箇所で参照している間に、可変参照で値を書き換えてしまう可能性があるため
code:rust
let mut s = String::from("hello");
{
let s1 = &mut s; // mutable borrow occurs here
let _s0 = &s; // immutable borrow occurs here
s1.push_str(" world"); // mutable borrow later used here
}
println!("{}", s);
同時に存在しなければ、可変参照から不変参照を作ることもできる
code:rust
let mut s = String::from("hello");
{
let _s1 = &s; // _s1 は不変参照
}
ツール周辺
code:sh
# ツーリチェイン周りのアップデート
rustup update
# パッケージ管理など
cargo new {project}
# ライブラリ用プロジェクト
cargo new --lib {project}
メモ
&strとStringの違い
https://gyazo.com/062c49ed144fa0ad93d27fbca2cc971c
ツールチェイン周り
rustup => ツールチェインマネージャー
https://gyazo.com/41bbab7ae10e9f06a1b5cdfea5296d93
コンパイルについて
zigを使ってクロスコンパイルする方法
参考資料
zigのクロスコンパイルについて
Rustでzigを使ったコンパイル例
実際にやってみる
code:sh
# Linuxでzigをインストール
mkdir ~/.zig
cd ~/.zig
tar xfv /tmp/zig/zig.tar.xz
sudo ln -s $PWD/zig /usr/bin/
# zigを使ってARMのLinuxで64のLinuxバイナリをビルド
ubuntu@dev github.com/skanehira/rjo $ uname -a
Linux dev 5.13.0-52-generic #59-Ubuntu SMP Wed Jun 15 20:20:55 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux ubuntu@dev github.com/skanehira/rjo $ rustup target add x86_64-unknown-linux-gnu
info: downloading component 'rust-std' for 'x86_64-unknown-linux-gnu'
info: installing component 'rust-std' for 'x86_64-unknown-linux-gnu'
26.0 MiB / 26.0 MiB (100 %) 14.2 MiB/s in 1s ETA: 0s
ubuntu@dev github.com/skanehira/rjo $
ubuntu@dev github.com/skanehira/rjo $ cat zigcc.sh
zig cc -target x86_64-linux-gnu $@
ubuntu@dev github.com/skanehira/rjo $ cat .cargo/config.toml
linker = "./zigcc.sh"
ubuntu@dev github.com/skanehira/rjo $ CC="./zigcc.sh" cargo build --target x86_64-unknown-linux-gnu
...
ubuntu@dev github.com/skanehira/rjo $ file target/x86_64-unknown-linux-gnu/debug/rjo
target/x86_64-unknown-linux-gnu/debug/rjo: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.0.0, with debug_info, not stripped
crossを使ったクロスコンパイル
code:sh
cross build --target xxxx
cargo-zigbuildを使ったクロスコンパイル
code:sh
cargo install cargo-zigbuild
cargo zigbuild --release --target xxx
クレートとモジュール
https://image.itmedia.co.jp/ait/articles/2206/24/l_tyamauchi_20220624Rust12_zu01_590px.png
ユースケースごとのクレートを紹介しているやつ
Rustドキュメント
フレームワーク
axum
async-graphql