moving soon →kajiri.dev

wasmを勉強する2

December 31, 2020

commit history
  1. 2020/12/29 03:40:40 8628dd7
headline

前回の続き

今回はこれです。

ここまできた。何が入っているか。このexternとpubがいまいちわかってないけど、多分、importとexportなんだろう

#![allow(unused_variables)]
fn main() {
extern crate cfg_if;
extern crate wasm_bindgen;

mod utils;

use cfg_if::cfg_if;
use wasm_bindgen::prelude::*;

cfg_if! {
    // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
    // allocator.
    if #[cfg(feature = "wee_alloc")] {
        extern crate wee_alloc;
        #[global_allocator]
        static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
    }
}

#[wasm_bindgen]
extern {
    fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet() {
    alert("Hello, wasm-game-of-life!");
}

}

ここまできた。

あれ、説明と違うぞ

# 解説
pkg/
├── package.json
├── README.md
├── wasm_game_of_life_bg.wasm
├── wasm_game_of_life.d.ts
└── wasm_game_of_life.js
# 実際
pkg/
├── package.json
├── README.md
├── wasm_game_of_life.d.ts
├── wasm_game_of_life.js
├── wasm_game_of_life_bg.js
├── wasm_game_of_life_bg.wasm
└── wasm_game_of_life_bg.wasm.d.ts

バージョン変わったん?

そういえば前回はbg.jsがなくてうまく動かなかったな。今回は自動で生成された。なんか違うんか?

で、npm run startしたら、前回と同じ用にアラートが表示された。

exercisesまできた。

え、greet関数を変更しろって?知らないよ。さっき同じようなの見たからできるけど。 link

extern crate wasm_bindgen;

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern {
    pub fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}

うーん、まーexternがimport、pubがexportなんだろうけど、しっくりこない。ちょっと調べるか。

pub

コンパイラに何かを公開すると指示するには、定義の先頭にpubキーワードを追記します。

extern

(訳)このexternキーワードは、Rustの2か所で使用されています。1つはcrate キーワードと組み合わせて、Rustコードにプロジェクト内の他のRustクレートを認識させるためのものextern crate lazy_static;です。他の用途は、外部関数インターフェース(FFI)です。

extern関数を使用して外部コードを呼び出す

(訳)時々、あなたのRustコードが他の言語で書かれたコードと相互作用する必要があるかもしれません。このために、Rustには外部関数インターフェース(FFI)の作成と使用を容易にするキーワードexternがあります。FFI はプログラミング言語が関数を定義し、別の (外国の) プログラミング言語がそれらの関数を呼び出すことを可能にする方法です。

externで別の言語から呼び出しを可能にする。Cの部分はC言語のinterfaceに従う。C言語のきまりに従う感じかな?

もっといいのあった

wasm-bindgen

use wasm_bindgen::prelude::*;

// Import the `window.alert` function from the Web.
#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

// Export a `greet` function from Rust to JavaScript, that alerts a
// hello message.
#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}

予想通りだった。externでimport。

しかし、Cの部分はよくわかんないな。JSとかになるんじゃないのか?JavaScriptエンジンはC++でlink書かれてる。(spider monkey)とかは別かな?。

まあ、いいや。で、pubがexportしてると。

fnは関数定義

extern “C”でalertをimport。pub fn greetの内部でalertを使う。alertはJavaScriptのalert。引数には、、なんだこれ、&format!って。rubyっぽいな

doc.rust-js.rs

format!: フォーマットされたテキストを文字列(String)型に書き込みます。

doc.rust-lang.org

format!("test");
format!("hello {}", "world!");
format!("x = {}, y = {y}", 10, y = 30);

引数を順番に{}に取り込むようだ。

&はポインタ?

stackoverflow

所有権

所有権は読むと面白い。

所有権 参照と借用

fn main() {
    let s1 = String::from("hello");

    let len = calculate_length(&s1);

    // '{}'の長さは、{}です
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

まず、変数宣言と関数の戻り値にあったタプルコードは全てなくなったことに気付いてください。 2番目に、&s1をcalcuate_lengthに渡し、その定義では、String型ではなく、&Stringを受け取っていることに注目してください。 これらのアンド記号が参照であり、これのおかげで所有権をもらうことなく値を参照することができるのです。 図4-5はその図解です。

いろいろしらべたけど、&format!はわからん。まあいいや。

&で所有権を移さず、参照を使う。&xって感じで値が返ってくることはわかったから、関数もたぶん、値が返ってくるんだろう。

とりあえずさっきのgreetに引数渡せるようになった。ok。

github

link


contact