C++代码编译为 WebAssembly
准备工作
- 安装 Emscripten SDK
- 准备好 C++代码
- 安装 Emscripten SDK
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source./emsdk_env.sh
-
进入 c++代码所在目录
-
编译 C++代码
3.1. 对 c++代码进行改造`在默认的情况下,编译之后只有 main 函数会保存,其他函数不会保存,如果需要保存其他函数,需要在 c++代码中添加以下代码
#include <emscripten.h>
extern "C" {
EMSCRIPTEN_KEEPALIVE
void function1();
void function2();
}
这样编译之后,function1 会保存下来,function2 不会保存下来。
3.2. 编译
3.2.1 一般的编译命令如下:
emcc main.cpp -s WASM=1 -o main.html
3.2. 如果有多个源文件,可以用下面的命令:
emcc main.cpp file1.cpp file2.cpp -s WASM=1 -o main.html
3.3. 如果需要在 js 调用的时候传入参数,可以用下面的命令:
emcc main.cpp -o main.html -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=["getValue", "setValue"] -s "EXPORTED_FUNCTIONS=['_malloc','_free']"
3.4. 如果在编译之后使用报错Uncaught RuntimeError: memory access out of bounds
,可能是内存分配不足导致的,可以用下面的命令:
emcc main.cpp -o main.html -s WASM=1 -s INITIAL_MEMORY=1024mb -s TOTAL_STACK=67108864 -s ALLOW_MEMORY_GROWTH=1
4.编译完成后,会在当前目录生成 main.html 文件,用浏览器打开即可运行。
4.1. 如果需要在 js 调用的时候传入参数,可以在 js 代码中使用Module.getValue()
和Module.setValue()
方法。
4.2. 在 js 中有两种方式可以调用 wasm 代码: 方法一只能使用 number 类型
js// 方式 1: const result = Module.ccall('add', 'number', ['number', 'number'], [1, 2]); console.log(result); // 方式 2: // 先创建内存 var size_of_struct0_T = 8 + 200 _ 8 + 200 _ 8; // 8 是 struct0 的头部大小,200 是数组大小 // 分配内存 var map = Module._malloc(size_of_struct0_T) // 填充 Lat 和 Lon 数据 coordinates.forEach((coord, i) => { Module.setValue(map + i _ 8, coord.Lat, 'double') // Lat[i] Module.setValue(map + 200 _ 8 + i _ 8, coord.Lon, 'double') // Lon[i] }) Module.setValue(map + 200 _ 8 + 200 * 8 + 4, 4, 'double') const data = Module._CoverMapObsPlan(map, pyg, obs, struct3_ptr, wpCnt, wp, wpLen, wpArea, wpTime, wpYaw, Err) // 解析结果,要看 c++文件怎么写的 // 释放内存 Module._free(map)
如果对C++代码熟悉的话,可以比较快的上手编译为wasm。如果对内存分配不熟悉,比较会比较慢。