

RustでWebAssemblyにコンパイルした時にエラーが出てしまいます。

[code]

    //rust
    extern crate rand;
    use rand::Rng;
    
    fn main() {
        let secret_number = rand::thread_rng().gen_range(1, 101);
        secret_number;
    }
    
[/code]

[code]

    //toml
    [package]
    name = "main"
    version = "0.1.0"
    authors = ["akats"]
    edition = "2018"
    
    [dependencies]
    rand="*"
    
[/code]

これを`rustc main.rs`でコンパイルした時、次のエラーがでます。

[code]

    or[E0464]: multiple matching crates for `rand`
     --> main.rs:1:1
      |
    1 | extern crate rand;
      | ^^^^^^^^^^^^^^^^^^
      |
      = note: candidates:
              crate `rand`: \\?\C:\Users\akats\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\x86_64-pc-windows-msvc\lib\librand-453efbf1160c222c.rlib
              crate `rand`: \\?\C:\Users\akats\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\x86_64-pc-windows-msvc\lib\librand-9c0cd53839437cf2.rlib
              crate `rand`: \\?\C:\Users\akats\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\x86_64-pc-windows-msvc\lib\librand-6d48c3cad20b5526.rlib
    
    error[E0463]: can't find crate for `rand`
     --> main.rs:1:1
      |
    1 | extern crate rand;
      | ^^^^^^^^^^^^^^^^^^ can't find crate
    
    error: aborting due to 2 previous errors
    
    Some errors occurred: E0463, E0464.
    For more information about an error, try `rustc --explain E0463`.
    
    
[/code]

普通にRustだけで出力するとうまくいきますが何がダメなのかわかりません。よろしくお願いします。


CC BY-SA 4.0
2019-04-13T14:17:28.923
54143
2019-04-18T06:53:51.020
2019-04-17T12:22:30.243
19110
29881
question
rust webassembly
wasmでランダムな値を取得したい


randはRust本体に含まれる標準ライブラリ(libstd)ではなく外部のcrateですので、それをダウンロードしてビルドしてリンクするには基本的にはrustcではなくcargoを使用する必要があります。

[code]

    cargo build --target wasm32-unknown-unknown
    
[/code]

とすれば`target/wasm-unknown-unknown/debug`以下に`wasm`が拡張子になったファイルがあるはずです。

npmとの連携やwasm-bindgen等の利用についてはMozillaの以下の資料が参考になると思います（和訳が途中までですが）  
<https://developer.mozilla.org/ja/docs/WebAssembly/rust_to_wasm>


CC BY-SA 4.0
2019-04-14T15:32:06.260
54160
2019-04-14T15:32:06.260
9572
54143
answer


termoshttさんの言っていることに加えて以下を`Cargo.toml`に追記すると`.wasm`ファイルを生成できるはずです。

[code]

    [lib]
    crate-type = ["cdylib"]
    
[/code]

この記述の役割が気になる場合は[The Manifest Format](https://doc.rust-
lang.org/cargo/reference/manifest.html#building-dynamic-or-static-
libraries)を参照するとよいでしょう。

しかしこれでもまだ`rand`クレートが動作しないはずです。  
なぜかというとWebAssemblyはWebとは独立に定義された仕様でシンプルな計算命令しか持たないのですが、`wasm-unknown-
unknown`はそのピュアwasm向けのターゲットなので乱数の種を供給する方法が一切ないからです。  
JSが乱数関連のAPIを持っているのでそこから乱数の種を供給しようとしても、JSの関数のwasmへのインポートは自明でないので普通何らかのJSとwasmをブリッジするツールに頼ることになるのですが、当然インポートの仕組みがツール毎に違い、そのどれかをデフォルトにすることなんてできないからです。  
(インポートの仕組みは[MDNのドキュメント](https://developer.mozilla.org/ja/docs/WebAssembly/Understanding_the_text_format)が参考になります)

そこで、以下のような方法が考えられます。

  1. `rand::rngs::StdRng`を`rand::SeedableRng`トレイトを通して初期化する
  2. `wasm-bindgen`を利用する
  3. `stdweb`を利用する
  4. `wasm-unknown-wasi`をターゲットにする

おすすめは2, 3です。  
1は定数で初期化すると当然実行するたびに決まった順序で乱数を返してしまいます。  
自力でJSの関数をインポートして乱数の種を得ることもできますが面倒ですし、ハマりどころもあります。  
それでもやりたいなら次のリンクを参考にしてください。  
[ツールを使わないwasm開発の解説](https://www.reddit.com/r/rust/comments/9t95fd/howto_setting_up_webassembly_on_stable_rust/)、[インポートの解説](https://developer.mozilla.org/ja/docs/WebAssembly/Understanding_the_text_format)、[JSで乱数を得るためのメソッド](https://developer.mozilla.org/ja/docs/Web/API/RandomSource/getRandomValues)

2, 3は乱数の種をJavaScriptの関数から供給する方法で、例えば2なら`rand`クレートの`wasm-
bindgen`フィーチャを有効にした状態で`wasm-bindgen`を使ったコードを書くことになります。  
自分は`wasm-bindgen`しか使ったことがないのですが一応2のほうをよりおすすめしておきます。  
`wasm-
bindgen`の使い方は[termoshttさんが挙げてくれているページ](https://developer.mozilla.org/ja/docs/WebAssembly/rust_to_wasm)や[Rust
and WebAssembly](https://rustwasm.github.io/docs/book/)が参考になります。

4は将来的にいい選択肢になりそうですがまだ使えません。


CC BY-SA 4.0
2019-04-16T14:07:20.213
54213
2019-04-18T06:53:51.020
2019-04-18T06:53:51.020
28137
28137
54143
answer