第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を開催した。
改めて、レイヤが低い言語というのが少しだけわかった気がする。
今週はプルリクエストなし。