今年の言語はRust その55
Rustを学びます
Rustの日本語ドキュメント 2nd Edition
https://doc.rust-jp.rs/book/second-edition/
オリジナル(英語)
https://doc.rust-lang.org/book/
実行環境
$ cargo -V
cargo 1.33.0 (f099fe94b 2019-02-12)
$ rustup -V
rustup 1.17.0 (069c88ed6 2019-03-05)
$ rustc --version
rustc 1.33.0 (2aa4c46cf 2019-02-28)
$ cat /proc/version
Linux version 4.14.97-74.72.amzn1.x86_64 (mockbuild@gobi-build-64002)
(gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC))
#1 SMP Tue Feb 5 20:59:30 UTC 2019
$ uname -a
Linux ip-10-100-0-8 4.14.97-74.72.amzn1.x86_64
#1 SMP Tue Feb 5 20:59:30 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/\*release
NAME="Amazon Linux AMI"
VERSION="2018.03"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2018.03"
PRETTY_NAME="Amazon Linux AMI 2018.03"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2018.03:ga"
HOME_URL="http://aws.amazon.com/amazon-linux-ami/"
Amazon Linux AMI release 2018.03
19. 高度な機能
通常なら飛ばして後から考えますが、今回は全写経が目的なので、
理解朧げでもひたすら写経して進んでいきます。
19.1 Unsafe Rust
Rustには、Unsafe Rust という裏Rustがあるらしい。
(C#でもたまに出てきますね)
生ポインタを参照外しする
fn main() {
let mut num = 5;
let _r1 = &num as *const i32;
let _r2 = &mut num as *mut i32;
}
アドレスを指定してポインタを作ることができる。
しかし、 safe コードではアクセスはできない。
fn main() {
let address = 0x012345usize;
let r = address as *const i32;
}
unsafe コードを利用してアクセスする
fn main () {
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
unsafe {
println!("{:?}", *r1);
println!("{:?}", *r2);
}
}
unsafeな関数やメソッドを呼ぶ
unsafe fn dangerous() {
}
fn main() {
unsafe {
dangerous();
}
}
unsafeコードに安全な抽象化を行う
fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
let len = slice.len();
assert!(mid <= len );
(&mut slice[..mid], &mut slice[mid..])
}
fn main() {
let mut v = vec![1,2,3,4,5,6];
let r = &mut v[..];
let (a, b) = r.split_at_mut(3);
assert_eq!(a, &mut [1, 2, 3]);
assert_eq!(b, &mut [4, 5, 6]);
}
use std::slice;
fn split_at_mut(slice: &mut[i32], mid:usize) -> (&mut[i32], &mut[i32]) {
let len = slice.len();
let ptr = slice.as_mut_ptr();
assert!(mid <= len );
unsafe {
( slice::from_raw_parts_mut(ptr, mid),
slice::from_raw_parts_mut(ptr.offset(mid as isize), len-mid)
)
}
}
fn main() {
let mut v = vec![1,2,3,4,5,6];
// unsafeブロックは不要で呼び出せる
let (a, b) = split_at_mut(&mut v, 3);
println!("{:?}", a);
println!("{:?}", b);
assert_eq!(a, &mut [1, 2, 3]);
assert_eq!(b, &mut [4, 5, 6]);
}
extern 関数を使用して外部のコードを呼び出す
RustでCの関数を呼べた!
extern "C" {
fn abs(input: i32 ) -> i32;
}
fn main() {
unsafe {
println!("Absolute value of -3 according to C: {}", abs(-3));
}
}
CからRustを呼び出す. #[no_manage] を読んで、コンパイラが関数名をマングルしないように指示します。
#[no_manage]
pub extern "C" fn call_from_c() {
println!("Just called a Rust function from C!");
}
可変で静的な変数にアクセスしたり、変更したりする
Rustではグローバル変数は、static変数と呼ばれる
static HELLO_WORLD: &str = "Hello, world!";
fn main() {
println!("name is: {:?}", HELLO_WORLD);
}
static変数を改変するには、unsafeである。
これはマルチスレッドの場合に、データ競合になる可能性があるからである。
static mut COUNTER: u32 = 0;
fn add_to_count(inc: u32) {
unsafe {
COUNTER += inc;
}
}
fn main() {
add_to_count(3);
unsafe {
println!("COUNTER: {:?}", COUNTER);
}
}
unsafe なトレイトを実装する
unsafe trait Foo {
}
unsafe imple Foo for i32 {
}
長かった。
が、unsafeの大まかな使い方、注意点は勘所が付いた気がする。
イエス!
あと、5/8にRustの最新本がでるみたいです! (現在5/6)
実践Rust入門[言語仕様から開発手法まで] 単行本(ソフトカバー) – 2019/5/8
※アフェっときます