TypeScriptからWebAssemblyを生成するAssemblyScriptを試す
WebAssemblyはプログラミング言語ではなく、様々なプログラミング言語から生成されるWebブラウザ上で実行できるバイナリフォーマットになります。基本はRustやC、C++であり、他にもGo、Java、Kotlin、Swiftなど様々なプログラミング言語が対応しています。
しかし複数のプログラミング言語を混ぜて開発するのは要員確保も大変です。そこで注目したいのがTypeScriptからWebAssemblyファイルを生成するAssemblyScriptです。今回はその特徴を紹介します。
JavaScriptの関数を呼び出せる
AssemblyScriptではdeclareを使って関数を定義することで、JavaScript側の関数を呼び出せます。例えば以下はsayHello関数を呼び出しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare function sayHello(): void; | |
sayHello(); |
そしてJavaScript側では次のように記述します。mainの中でsayHelloという関数を定義することで、AssemblyScriptからJavaScriptの関数呼び出しを可能にしています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
WebAssembly.instantiateStreaming(fetch("../out/main.wasm"), { | |
main: { | |
sayHello() { | |
console.log("Hello from WebAssembly!"); | |
} | |
}, | |
env: { | |
abort(msg, file, line, column) { | |
console.error("abort called at main.ts:" + line + ":" + column); | |
} | |
}, | |
}) |
JavaScriptからAssemblyScriptの関数を呼び出す
逆にJavaScriptからAssemblyScriptの関数を呼び出す場合はexportを使って関数を公開します。型を指定しなければなりません。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function add(x: i32, y: i32): i32 { | |
return x + y; | |
} | |
export function minus(x: i32, y: i32): i32 { | |
return x – y; | |
} |
これで、WebAssemblyファイル読み込み後の result.instance.exports
の中に関数が入ります。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
exports.minus(23, 20); | |
// -> 3 |
文字列を返す場合
文字列の場合は多少注意が必要です。まず関数の定義の時点で文字列の長さも返すように定義します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare function sayHello(msg: string, len: usize): void; | |
export function say(): void { | |
const str: string = "hifive"; | |
sayHello(str, str.length); | |
} |
次に受け取った側ではメモリ中の値を読み取り、デコードしなければなりません。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sayHello(index) { | |
const length = mem.getUint32(index,true); | |
const array = new Uint16Array(mem.buffer,index + 4,length); | |
const str = new TextDecoder('utf-16').decode(array); | |
console.log(`Hello ${str}, from WebAssembly!`); | |
} |
memはWebAssemblyファイルを読み込んだ後 result.instance.exports.memory.buffer
で取得できます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mem = new DataView(result.instance.exports.memory.buffer); |
まとめ
WebAssemblyがTypeScriptで書けるようになれば、 TypeScriptだけでフロントエンドの開発が完結できます。もちろんサブセットなので全ての機能が使える訳ではありません。しかし高速な処理が必要になった際に、AssemblyScriptであれば書き慣れた構文でWebAssembly化できるメリットが大きいでしょう。
AssemblyScript/assemblyscript: A TypeScript to WebAssembly compiler 🚀
コメントは受け付けていません。