LoginSignup
15
2

More than 1 year has passed since last update.

GASで始めるWebAssembly

Last updated at Posted at 2022-12-15

はじめに

本記事はQualiArts Advent Calendar 2022 16日目の記事になります

ここでは Google Apps Script(以下GAS) を用いて WebAssembly(以下wasm) に入門するための紹介を行います
GAS や wasm, Rust などの基本的な説明は行いません

なぜGAS?

GASの実行環境もV8ランタイムがサポートされており、wasmが使えた場合はGASやspreadsheetなどを用いる業務に活かすことができそうだと思い検証してみました

準備するもの

  • 生成したwasmファイルをホストできる環境

wasmファイルの生成

GASではTextEncoderなど対応されていないAPIがあるためそのままではGoなど一部の言語を用いて生成したwasmを使用することはできません
もしGoを用いて実行したい場合はwasm_exec.jsで実装してあるAPIをGAS向けに実装しなおす必要などがあります。(未検証)

そのため、今回はRustを用いてwasmファイルを生成します

src/lib.rs
#[no_mangle]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

今回は wasm32-unknown-unknown をターゲットとし、ビルドします
wasm32-wasi でも可能ですが手順が少し変わります。(後述)

$ cargo build --target=wasm32-unknown-unknown

./target/wasm32-unknown-unknown/debug 配下にpackage名のwasmファイルが生成されているはずなのでそれをホストできる環境などにアップロードします

GAS

まずは WebAssembly.Instance オブジェクトを生成します

let instance;
(async () => {
  const resp = UrlFetchApp.fetch('ホストしたwasmファイルのURL')
  const obj = await WebAssembly.instantiate(new Uint8Array(resp.getContent()).buffer);
  instance = obj.instance
})();

GASにはfetch APIは存在しないため、UrlFetchApp.fetchを用いてファイルを取得します
取得したファイルデータをバイナリコードに変換しWebAssembly.instantiate()を用いてinstanceを生成します

現在では、WebAssembly.instantiateStreaming()を用いることが推奨されていますがGASには存在しないためWebAssembly.instantiate()を使用します
そのため、今回使用するホストサーバーが MIMEタイプ application/wasmで返してくれなくても問題ありません

function main(){
  console.log(instance.exports.add(5, 10))
}

後は生成されたinstanceからエクスポートされたwasm関数を呼び出すだけです

スクリーンショット.png

wasm32-wasiの場合

wasm32-wasiをターゲットにビルドする場合は必要となるAPIを実装する必要があります。

let instance;
(async () => {
  const resp = UrlFetchApp.fetch('ホストしたwasmファイルのURL')

  var importObject = {
    // 必要となるAPIの実装
    wasi_snapshot_preview1: {
      proc_exit: () => {...},
      fd_write: () => {...},
      fd_prestat_get: () => {...},
      fd_prestat_dir_name: () => {...},
      environ_sizes_get: () => {...},
      environ_get: () => {...}
    },
  }
  const obj = await WebAssembly.instantiate(new Uint8Array(resp.getContent()).buffer, importObject);
  instance = obj.instance
})();

以下記事がとても参考になります

おわりに

GASでもwasmを動かすことができました
今回はwasmを自作しましたが、wapm.ioなどすでにホストサービスが存在しているためもっとwasmが賑わったらGASでもwasmの恩恵を受けられるかもしれません
wasm楽しいのでこれからも色々と追っていきたいと思います!

15
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
2