今年の言語は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

※アフェっときます

广告
将在 10 秒后关闭
bannerAds