👻

React+TypeScriptでWebAssembly011。React+TypeScript。ReactTsでWasm呼び出しのまとめ

2024/01/31に公開

<- React+TypeScriptでWebAssembly010
                    React+TypeScriptでWebAssembly012 ->

Abstract

前回、WebAssemblyで、jsからC++の関数呼び出しを実装できた。
なので、今回はReact+TypeScriptからの呼び出しを実装する。

結論

今回の成果物はココ↓
https://github.com/aaaa1597/ReactTs-WebAsm011

前提

準備

windowsだよ。

1.テンプレートのソースコード一式を取得

github取得
$ cd ~
$ git clone https://github.com/aaaa1597/reacttscppwasm_tmplate.git
$ mv reacttscppwasm_tmplate ReactTs-WebAsm011
$ cd ReactTs-WebAsm011/

2.cppmain.wasmとcppmain.jsを上書きする。

ダウンロードして上書き。

3. npm installを実行。

適当にプロジェクトフォルダを作る。
$ cd D:\Products\React.js\ReactTs-WebAsm011
$ npm install

4. VSCodeで開く。

ReactTs-WebAsm011\reacttsフォルダで右クリック。

5.cppmain.jsの修正。

見やすくするためにcppmain.jsをフォーマット。

Prettier コードフォマッターをインストールして、

     ↓
Shift + Ctrl + P → Format Document (Forced)を実行

     ↓
いい感じに整形してくれる。

6. Moduleのエクスポート化

cppmain.js(1行目)
- 1: var Module = typeof Module != 'undefined' ? Module : {};
+ 1: export var Module = typeof Module != 'undefined' ? Module : {};

7. cppmain.wasmの読込み元を修正。

cppmain.wasmをpuclic\wasmに配置するのを前提に。

cppmain.js(531行目らへん)
- 715:   wasmBinaryFile = 'hello.wasm';
+ 715:   wasmBinaryFile = 'wasm/cppmain.wasm';

8.CMakeLists.txtの修正

CMakeLists.txt
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s USE_ZLIB=1 -s ASSERTIONS=1 -s DISABLE_EXCEPTION_CATCHING=0 --bind -O3 -s LLD_REPORT_UNDEFINED -s DEMANGLE_SUPPORT=1")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s USE_ZLIB=1 -s ASSERTIONS=1 -s DISABLE_EXCEPTION_CATCHING=0 -lembind -O3 -s LLD_REPORT_UNDEFINED -s DEMANGLE_SUPPORT=1")

--bind を -lembind に変更。

9. App.tsx修正

App.tsx
import React, { useEffect, useRef } from 'react';
import './App.css';

class point {
  x: number;
  y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return '('+this.x+','+this.y+')';
  }
}

class rect {
  x: number;
  y: number;
  w: number;
  h: number;
  constructor(x: number, y: number, w: number, h: number) {
    this.x=x;
    this.y=y;
    this.w=w;
    this.h=h;
  }
  toString() {
    return '('+this.x+','+this.y+','+this.w+','+this.h+')';
  }
}

function App() {
  const refWasm = useRef<any>(null)
  const refTextin = useRef<HTMLTextAreaElement>(null!)
  const refTextout = useRef<HTMLTextAreaElement>(null!)

  /* wasm読込み */
  const h = require('./cppmain.js');
  h.Module.onRuntimeInitialized = () => {
    console.log("Wasm loaded.");
    refWasm.current = h.Module
  }

  useEffect(() => {
    refTextin.current.rows = 5
    refTextout.current.rows = 5
  });

  const bclick = () => {
    const textout = refTextout.current;
    const wasm = refWasm.current;
    if(!textout && !wasm) return;
		textout.value ="f1(1,2)=" + wasm.f1(1,2) + "\n";
		textout.value+="f2(2.5,3.5)=" + wasm.f2(2.5, 3.5) + "\n";
		textout.value+="f3('aaa', 'bbbb')=" + wasm.f3('aaa', 'bbbb') + "\n";
		const arg41=[1,2,3,4], arg42=[5,6,7,8];
		textout.value+="f4([1,2,3,4], [5,6,7,8])=" + wasm.f4(arg41, arg42) + "\n";
		const arg51=new Uint8Array([1,2,3,4]), arg52=new Uint8Array([5,6,7,8]);
		textout.value+="f5(new Uint8Array([1,2,3,4]), new Uint8Array([5,6,7,8]))=" + wasm.f5(arg51, arg52) + "\n";
		const arg61=['aa','bb','cc','dd'], arg62=['ee','ff','gg','hh'];
		textout.value+="f6(['aa','bb','cc','dd'], ['ee','ff','gg','hh'])=" + wasm.f6(arg61, arg62) + "\n";
		const arg71=new point(1,2), arg72=new point(3,4);
        ↓①この行の使い方が分からん
//		textout.value+="f7(new point(1,2), new point(3,4))=" + wasm.f7(arg71, arg72) + "\n";
		textout.value+="f8({x2:1, y2:2},{w2:3, h2:4})=" + JSON.stringify(wasm.f8({x2:1, y2:2},{w2:3, h2:4}));
  }

  return (
    <div className="App">
      hello world!!
      <button onClick={bclick}>Click</button>
      <textarea id="textin" ref={refTextin}></textarea>
      <textarea id="textout" ref={refTextout}></textarea>
    </div>
  );
}

export default App;

①の行の使い方が分からんかったけど、後はうまくいった。

10.サーバ起動

サーバ起動
$ cd D:\Products\React.js\ReactTs-WebAsm011\reactts
$ npm start

11.サーバにアクセス。

ブラウザから http://localhost:8080/ にアクセスする。


出来た!!

func7()のJSオブジェクト, JSオブジェクト, JSオブジェクトの関数呼び出しがうまくできんかったけど、今のところ使う予定ないし、宿題ってことで。


<- React+TypeScriptでWebAssembly010
                    React+TypeScriptでWebAssembly012 ->

Discussion