WASM阶段验证

一.WASM简介

  1. WebAssembly 是一种可以在浏览器端运行二进制格式代码的技术,他的目标则是想提供接近Native code的执行效率的技术体验。 相较于文本类型的JavaScirpt而言,它拥有更小的体积,更短的加载时间,和更好的执行性能等特点 。WebAssembly 允许你使用Rust或者C/C++等静态语言来编写,并生成目标文件后缀为wasm的二进制格式文件。通过Fetch或者Ajax与WebAssembly提供的 API ,我们可以实现JavaScript与wasm模块的混用。
  2. 转换流程:
  1. 存在的问题:默认情况下,Emscripten生成的代码只会调用main()函数,其他函数将被视为无用代码。为了避免这件事发生,我们需要在C函数名之前,添加EMSCRIPTEN_KEEPALIVE(在emscripten.h中声明)或定义一个函数导出宏,从而使得在js中可以顺利的调用c函数。

二.环境搭建(基于Win环境)

  1. 安装SDK
git clone https://github.com/juj/emsdk.git 
  1. 使用git bash命令行工具,这一点很重要,因为git bash下的环境是模拟linux的;
  2. 切换到emsdk根目录下,执行如下命令,拉取安装SDK环境(这一步时间非常长):
./emsdk update
./emsdk install latest
  1. 执行上一步中安装好的环境:
./emsdk activate latest
  1. 配置环境变量,注意这里配置的环境变量是临时,因为emcc所需的环境很多,故每次关闭掉git bash重新打开之后都需要配置环境:
source ./emsdk_env.sh

以上就是WASM环境变量的搭建过程,在这其中,我在第三步,使用"./emsdk install latest"安装的过程中,用了快两天的时间,故安装过程需要耐心等待

三.Hello World验证

将前文中的git bash窗口关闭,重新进行程序的验证;

  1. 在emsdk目录内创建一个hello.c文件,代码内容为:
//hello.c
#include <stdio.h>

int main() {
    printf("hello,world!\n");
    return 0;
}
  1. 进入emsdk根目录下,打开git bash,执行"source ./emsdk_env.sh",启动环境变量,启动完之后,不要关闭窗口;
  1. 在hello.c文件目录下,执行“emcc hello.c -o hello.js”,将hello.c文件编译成hello.js文件,执行成功后,会生成hello.js和hello.wasm,则说明编译成功;
  2. 使用node hello.js,验证,成功输出结果:
  1. 使用html验证需要在http协议下可以验证;打开webstorm,新建一个html文件,在html文件中引入hello.js文件,在webstorm中运行,验证成功。
img
  1. 也可以执行"emcc hello.cc -o hello.html",可以直接生成基于emcc的测试界面,效果与前面的也是一样的,在这里要注意的是,生成的hello.html文件也是要在http下运行的。

四.js调用c函数

  1. 创建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;
}
  1. 在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测试了一下是没有出现警告的。所以不用担心警告的问题。