✨
React+TypeScriptで、TsxからWebAssembly呼び出し
Abstract
てっきり、JavaScriptからしかWebAssembly呼び出しできんのかと思っとったら、何のことない。App.tsxから呼べるやんか。前回のめんどくさいの何やったとっていうことで、App.tsxからWebAssemnbly呼び出してみた。
結論
今回の成果物はココ↓
前提
- windowsだよ。
- React+Typescriptの開発環境は構築済。 [環境構築]WindowsにVSCode+React+TypeScriptの開発環境を構築してみた。
- WebAssemblyのビルド環境も構築済み。[環境構築]Windowsで、WebAssemblyを初めてみた。
- テンプレートプロジェクトから作成。React-Ts-Template
ざっくり手順
- cppファイル生成 -> ビルド
- ビルドでできたwasmファイルをpublic配下にコピー
- App.tsxで呼び出す。
- 実行
手順詳細
- cppファイル生成 -> ビルド
rm React-Ts-Template ReactTs-WebAsm003
cd ReactTs-WebAsm003/src # プロジェクトフォルダに移動
mkdir asm-cpp # jsモジュール置き場を作成
type nul > asm-cpp/hello.cpp # hello.cppを自分で生成
hello.cppの中身
#include <stdio.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#else
#define EMSCRIPTEN_KEEPALIVE
#endif
extern "C" {
int EMSCRIPTEN_KEEPALIVE add(int a, int b){
return a + b;
}
int EMSCRIPTEN_KEEPALIVE sub(int a, int b){
return a - b;
}
} /* extern "C" */
で、ビルド
コマントプロンプト
<emsdkをインストールしたフォルダ>emsdk\emsdk_env.bat # <- コマントプロンプト起動の度に毎回実行。
emcc asem-cpp/hello.cpp -o asem-cpp/hello.js -sWASM=1 -sEXIT_RUNTIME=1 -sEXPORTED_RUNTIME_METHODS=ccall,cwrap
成功したら、フォルダ構成は以下の様になる。
$ プロジェクトフォルダ
~略~
└─src
│ ~略~
└─asm-cpp
hello.cpp
hello.js # <- 使わない。捨ててよし。
hello.wasm # <- ビルドで生成される
- ビルドでできたhello.wasmをpublic配下にコピー
コマントプロンプト
$ プロジェクトフォルダ
~略~
├─public
│ └─wasm
│ hello.wasm # <- ここにコピー
│ ~略~
│ └─asm-cpp
│ hello.wasm # <- これを、
- App.tsxで呼び出す。
helloif.js(wasmを呼び出すためのインターフェース)
-import React from 'react';
+import React, { useEffect, useState } from 'react';
import './App.css';
function App() {
+ const [count, setCount] = useState(0)
+ const getFromAsm = () => {
+ WebAssembly.instantiateStreaming(fetch("wasm/hello.wasm")).then(
+ (obj) => {
+ console.log('----------001')
+ const ret1 = (obj.instance.exports._Z3addii as CallableFunction)(11, 22);
+ console.log('retretret=', ret1);
+ setCount(ret1)
+ const ret2 = (obj.instance.exports._Z3subii as CallableFunction)(11, 22);
+ console.log('retretret=', ret2);
+ console.log('----------002')
+ return ret1
+ }
+ );
+ }
return (
<div className="App">
hello world!!
+ <button onClick={() => getFromAsm()}> Click {count} times</button>
</div>
);
}
export default App;
- 実行
出来た!!
前回より、こっちの方がスッキリ。全然、分かりやすくなった。
Discussion