Emscripten基础
Emscripten基础
Emscripten底层是LLVM编译器,作用就是将C/C++编译成asm.js
**TIPS: **asm.js是有Mozilla提出的JS子集,更大程度优化以提高执行速度,可以直接对应编译成机器指令执行

0、VsCode配置Emscripten环境
以macOS为例,需要在项目根目录下创建一个.vscode文件夹并创建c_cpp_properties.json
1 | { |
基于此配置即可在项目中引用emscripten.h并有相关的代码提示
1、C/C++调用JavaScript
使用EM_ASM是一个宏,可以在其中写js代码,如下
1 |
|
然后使用以下命令编译成asm.js并嵌入hello.html中
1 | emcc test.cpp -s WASM=1 -o hello.html |
可以使用vscode的Live Server插件开启一个本地服务器并打开该html,可以发现该alert
命令中的细节:
-s WASM=1表示指定编译目标为wasm,如果不设置改参数则默认生成纯js文件ams.js,其中WASM=1表示编译成wasm-o hello.html表示会生成一个HTML页面来运行这段代码,会生成- hello.wasm二进制wasm模块代码
- hello.js包含了用来在原生 C 函数js/wasm之间转换的胶水代码的js文件
- hello.html用来加载,编译,实例化你的wasm代码并且将它输出在浏览器显示上的一个HTML文件
2、JavaScript调用C/C++
EM_ASM执行的JS代码中也可以使用C/C++函数,如下所示
1 |
|
JS代码中需要使用C/C++函数需要使用Module.cwrap方法,该函数接受三个参数:
- 函数名称,使用引号包裹
- 该C函数返回值类型,若为void函数则将类型写作null(JS类型,而非C/C++类型)
- 函数参数类型,数组形式(JS类型)
该代码以下命令编译成asm.js并嵌入test.html中
1 | emcc test.cpp -s WASM=1 -s EXPORTED_FUNCTIONS='["_TestFunc","_main"]' -s EXPORTED_RUNTIME_METHODS='["cwrap"]' -o test.html |
其中-s EXPORTED_FUNCTIONS表示需要输出的函数名称数组,并在函数名称前加下划线
-s EXPORTED_RUNTIME_METHODS='["cwrap"]'表示导出 cwrap 运行时方法,用于在JavaScript中包装C函数
等价的,还可以使用Module.ccall方法,如下所示
1 |
|
Module.ccall方法也可以在EM_ASM中的JS方法中调用C方法,该函数接受四个参数:
- 函数名称,使用引号包裹
- 该C函数返回值类型,若为void函数则将类型写作null(JS类型,而非C/C++类型)
- 函数参数类型,数组形式(JS类型)
- 参数数组
该代码以下命令编译成asm.js并嵌入test.html中
1 | emcc test.cpp -s WASM=1 -s EXPORTED_FUNCTIONS='["_TestFunc","_main"]' -s EXPORTED_RUNTIME_METHODS='["ccall"]' -o test.html |
3、C/C++与JavaScript通信
C/C++可以通过传参的方式与JS函数进行通信,如下所示
1 |
|
其中EM_ASM_INT表示其中包含的JS函数返回值将是一个C/C++中int类型的数据
通过$n的方式表示第n-1个参数,第一个参数即为$0
ESM_ASM_INT方法第二个参数开始即为C/C++中需要传给JS函数的参数
多个参数的情况如下
1 |
|