シリーズ記事の目次
第 1 章 WebAssembly の概念
第 2 章 Emscripten の詳細説明
第 3 章 C\C++ の JavaScript 呼び出し
第 4 章 C\C++ の JavaScript 呼び出し
WebAssembly 第 3 章 JavaScript による C\C++ の呼び出し
序文
この記事は WebAssembly シリーズの第 3 章であり、いくつかの一般的なシナリオで JavaScript が C++ 関数を呼び出すために必要な操作手順、コンパイル コマンド、および特定のコードを紹介します。
私の環境
コンポーネント | バージョン |
---|---|
CentOS | 7 |
ドッカー | 20.10.7 |
emscripten/emsdk | 3.1.14 |
nginx | 1.18.0 |
クロム | 102.0.5005.115 |
1.コードコード
JavaScript が WASM をロードして実行する
目標
C++ で生成された wasm を実行して、Emscripten が提供するミニ HTML テンプレート ページに helloworld という単語を表示します。
wasm をロードするときに、ソース ファイルに main 関数があれば、それが自動的に実行されます。
まずC++でhello worldを書きます。
Sayhello.cpp
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char ** argv) {
printf("我是printf: Hello World\n");
cout<<"我是C++的cout "<<"你好,世界"<<endl;
return 0;
}
コンパイル
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk emcc sayhello.cpp -s WASM=1 --shell-file templates/shell_minimal.html -o helloworld.html
生成された js、wasm、html ファイルを Web サーバーに公開します。
ブラウザビューの結果
JavaScript が C++ 関数を呼び出す
ここでは、パラメーターのない関数と 2 つのパラメーターを持つ関数を C++ で作成し、JavaScript 側でそれらを使用する方法を示します。
C++ コード
コードは次のとおりです(例):
sayhello.cpp
#include <stdio.h>
#include <iostream>
#include <emscripten/emscripten.h>
using namespace std;
int main(int argc, char ** argv) {
printf("我是printf: Hello World\n");
cout<<"我是C++的cout "<<"你好,世界"<<endl;
return 0;
}
#ifdef __cplusplus
extern "C" {
#endif
void EMSCRIPTEN_KEEPALIVE myFunc1()
{
printf("我的函数已被调用\n");
return;
}
int EMSCRIPTEN_KEEPALIVE myFunc2(int a, int b)
{
printf("a+b=%d\n", a+b);
return a+b;
}
#ifdef __cplusplus
}
#endif
__cplusplus
C++ 環境が
EMSCRIPTEN_KEEPALIVE
Emscripten 固有かどうかを検出するために使用されるマクロ。最適化中に後続の関数を保持する必要があり、関数が JavaScript にエクスポートされることをコンパイラーに指示するために使用されます。
Sayhello.cppをコンパイルする
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk emcc --std=c++11 sayhello.cpp -s WASM=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']" --shell-file templates/shell_minimal.html -o helloworld2.html
helloworld2.html を編集する
関数呼び出しを手動でトリガーするボタンをページに追加します。
bodyタグ内に追加します
<button class="mybutton">运行我的函数</button>
ボタンクリックイベント監視をスクリプトセクションに追加します。
document.querySelector('.mybutton').addEventListener('click', function(){
alert('检查控制台');
var result = Module.ccall('myFunc1', // name of C function
null, // return type
null, // argument types
null); // arguments
let myfuncResult = Module.ccall('myFunc2', 'number', ['number', 'number'],
[1,2]);
console.log('myFunc2 result = '+myfuncResult);
});
ccall関数のシグネチャ
var result = Module.ccall(ident, returnType, argTypes, args);
パラメータ:
ident
: C エクスポートされた関数の関数名 (「_」アンダースコア接頭辞なし); :
returnType
C エクスポートされた関数の戻り値のタイプ (それぞれ「ブール」、「数値」、「文字列」、「ヌル」)関数の戻り値を示すブール値、数値、文字列、戻り値なし;
argTypes
: C エクスポート関数のパラメータ型の配列。パラメータのタイプは「数値」、「文字列」、「配列」で、それぞれ数値、文字列、配列を表します;
args
: パラメータ配列。
演算結果
要約する
以上が今日お話したいことです。この記事では C++ WASM を呼び出す JavaScript の使用方法を簡単に紹介するだけであり、Emscripten に関する詳細な内容はシリーズの他の章で提供されます (例: モジュール、コンパイル コマンドの詳細な説明) 、C++ 呼び出し Web API など)。