WASM阶段验证
一.WASM简介
- WebAssembly 是一种可以在浏览器端运行二进制格式代码的技术,他的目标则是想提供接近Native code的执行效率的技术体验。 相较于文本类型的JavaScirpt而言,它拥有更小的体积,更短的加载时间,和更好的执行性能等特点 。WebAssembly 允许你使用Rust或者C/C++等静态语言来编写,并生成目标文件后缀为wasm的二进制格式文件。通过Fetch或者Ajax与WebAssembly提供的 API ,我们可以实现JavaScript与wasm模块的混用。
- 转换流程:

- 存在的问题:默认情况下,Emscripten生成的代码只会调用main()函数,其他函数将被视为无用代码。为了避免这件事发生,我们需要在C函数名之前,添加EMSCRIPTEN_KEEPALIVE(在emscripten.h中声明)或定义一个函数导出宏,从而使得在js中可以顺利的调用c函数。
二.环境搭建(基于Win环境)
- 安装SDK
git clone https://github.com/juj/emsdk.git
- 使用git bash命令行工具,这一点很重要,因为git bash下的环境是模拟linux的;
- 切换到emsdk根目录下,执行如下命令,拉取安装SDK环境(这一步时间非常长):
./emsdk update
./emsdk install latest
- 执行上一步中安装好的环境:
./emsdk activate latest
- 配置环境变量,注意这里配置的环境变量是临时,因为emcc所需的环境很多,故每次关闭掉git bash重新打开之后都需要配置环境:
source ./emsdk_env.sh
以上就是WASM环境变量的搭建过程,在这其中,我在第三步,使用"./emsdk install latest"安装的过程中,用了快两天的时间,故安装过程需要耐心等待
三.Hello World验证
将前文中的git bash窗口关闭,重新进行程序的验证;
- 在emsdk目录内创建一个hello.c文件,代码内容为:
//hello.c
#include <stdio.h>
int main() {
printf("hello,world!\n");
return 0;
}
- 进入emsdk根目录下,打开git bash,执行"source ./emsdk_env.sh",启动环境变量,启动完之后,不要关闭窗口;

- 在hello.c文件目录下,执行“emcc hello.c -o hello.js”,将hello.c文件编译成hello.js文件,执行成功后,会生成hello.js和hello.wasm,则说明编译成功;
- 使用node hello.js,验证,成功输出结果:

- 使用html验证需要在http协议下可以验证;打开webstorm,新建一个html文件,在html文件中引入hello.js文件,在webstorm中运行,验证成功。


- 也可以执行"emcc hello.cc -o hello.html",可以直接生成基于emcc的测试界面,效果与前面的也是一样的,在这里要注意的是,生成的hello.html文件也是要在http下运行的。
四.js调用c函数
- 创建func.c文件,编写相关代码,代码前部定义函数导出宏,将func.c文件编译,生成func.js和func.wasm文件;
#ifndef EM_PORT_API
# if defined(__EMSCRIPTEN__)
# include <emscripten.h>
# if defined(__cplusplus)
# define EM_PORT_API(rettype) extern "C" rettype EMSCRIPTEN_KEEPALIVE
# else
# define EM_PORT_API(rettype) rettype EMSCRIPTEN_KEEPALIVE
# endif
# else
# if defined(__cplusplus)
# define EM_PORT_API(rettype) extern "C" rettype
# else
# define EM_PORT_API(rettype) rettype
# endif
# endif
#endif
#include <stdio.h>
EM_PORT_API(int) show_me_the_answer() {
return 42;
}
EM_PORT_API(float) add(float a, float b) {
return a + b;
}
- 在webstorm在创建html文件,把func.js和func.wasm放在同一目录下,创建如下的html文件:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
Module = {};
Module.onRuntimeInitialized = function() {
console.log(Module._show_me_the_answer());
console.log(Module._add(12, 5));
}
</script>
<script src="../js/func.js"></script>
</body>
</html>

在js中验证调用c++中的函数成功。
注:webstorm下运行出现警告,这个主要是webstorm自带web服务器的问题,我重新使用http-server测试了一下是没有出现警告的。所以不用担心警告的问题。