第75回です。前回はこちら。
[第75回の様子]
2023/04/19に第75回を開催した。
内容としてはRust By Example 日本語版20. 標準ライブラリのその他の「20.7. 引数処理」、「20.7.1. 引数のパース」、「20.8. 他言語関数インターフェイス」に取り組んだ。
参加者は自分を入れて6人。今回は詳しい人がドライバやってくれたので、色々と解説聴きながら進められてよかった!
[学んだこと]
- 20.7. 引数処理
- Rustでプログラムの引数を取得する場合std::env::args()関数を利用できる
- 戻り値はArgsという構造体で、イテレータになっているので、collect()してベクタに変換できる
use std::env; fn main() { let args: Vec<String> = env::args().collect(); println!("My path is {}.", args[0]); println!("I got {:?} arguments: {:?}.", args.len() - 1, &args[1..]); } // 実行結果はこうなる $ ./args 1 2 3 My path is ./args. I got 3 arguments: ["1", "2", "3"].
- Javaとかだとpublic static void main(String[] args)みたいにメイン関数の引数にコマンドライン引数が渡ってくるが、rustでは上でみたように標準ライブラリから取得する
- CとかもRustと似たような感じになっていて、それらはOSのない環境での実行のためにそうなっているらしい
- ちょっと面白い
- とはいえ通常はclapのようなクレートを使って引数を処理するのが一般的らしい
- clapの使い方はこんな感じ
use clap::Parser; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct Args { /// Name of the person to greet #[arg(short, long)] name: String, /// Number of times to greet #[arg(short, long, default_value_t = 1)] count: u8, } fn main() { let args = Args::parse(); for _ in 0..args.count { println!("Hello {}!", args.name) } }
- 20.7.1. 引数のパース
- clapなどのクレートを使わない場合、自分でパース処理を実装することになる
- サンプルコードは長いので省略...元サイトを参照してほしい
- 気になったのは、引数をStringで受け取ってi32にパースして処理する部分
- i32の最大値を入力して1を足した場合どうなるのだろう?と思ってやってみたら案の定パニックした
fn main() { // i32の最大値 let num = "2147483647"; let number: i32 = match num.parse() { Ok(n) => n, Err(_) => return, }; println!("{}", number + 1); } // パニックした時のエラー Compiling playground v0.0.1 (/playground) Finished dev [unoptimized + debuginfo] target(s) in 0.63s Running `target/debug/playground` thread 'main' panicked at 'attempt to add with overflow', src/main.rs:8:20
- ただ、これは必ずしもパニックするわけではなく、コンパイル時にリリースビルドにしているとオーバーフローするらしい
- 調べてみると、リリースビルドでもパニックさせる方法もあった
- 20.8. 他言語関数インターフェイス
- FFI、Foreign Function Interfaceというらしい
- C++だとextern Cとかって書いてCで利用できるようにするとか。みた事ある気がする
- RustでC言語のライブラリを利用するには、Cのライブラリを#[link]アトリビュートつきのexternブロックに宣言する
// libmライブラリをリンクする。 #[link(name = "m")] extern { fn csqrtf(z: Complex) -> Complex; fn ccosf(z: Complex) -> Complex; } // 単精度浮動小数の複素数型の最小限の実装 #[repr(C)] #[derive(Clone, Copy)] struct Complex { re: f32, im: f32, } // 外部ライブラリは常にunsafeなので、型安全にするためのラッパ fn cos(z: Complex) -> Complex { unsafe { ccosf(z) } }
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
改めて、レイヤが低い言語というのが少しだけわかった気がする。
今週はプルリクエストなし。