分类 默认 下的文章

使用WebAssembly
如果您只是对使用WebAssembly感兴趣的开发人员,则建议的启动方式是使用Emscripten(SDK)。 Emscripten是一个已经用于编译asm.js中的C / C ++的工具链,它是与WebAssembly类似的目标发明的JavaScript子集。 使用Emscripten,您可以更轻松地使用前面提到的Binaryen,并将其与自己的链结合起来。

一旦你安装了Emscripten,或者你已经从源代码编译了,你必须安装binaryen。

# these commands should be executed inside the emsdk folder
# on Linux or Mac OS X
# this step might take a while
./emsdk install --build=Release sdk-incoming-64bit binaryen-master-64bit
./emsdk activate --global --build=Release sdk-incoming-64bit binaryen-master-64bit
 
# on Windows
# this step might take a while
# if you are using Visual Studio 2017, append --vs2017
emsdk install --build=Release sdk-incoming-64bit binaryen-master-64bit
emsdk activate --global --build=Release sdk-incoming-64bit binaryen-master-64bit

然后激活编译环境,并确保设置正确的路径和变量,每次启动以下命令。

# the command should be executed inside the emsdk folder
# on Linux or Mac OS X
source ./emsdk_env.sh --build=Release
 
# on Windows
emsdk_env.bat --build=Release

终于,可以开始编码了。
WebAssemblyExample.c

#include <stdio.h>
 
int factorial(int n) {
  if (n == 0)
    return 1;
  else
    return n * factorial(n-1);
}
 
int main(int argc, char ** argv) {
  int number = 5;
  int fact = factorial(number);
  printf("The factorial of %d is %d", number, fact);
}

然后编译到WebAssembly并在浏览器中看到它。

emcc WebAssemblyExample.c -s WASM=1 -o WebAssemblyExample.html
# launch the local web server included with emscripten
emrun --no_browser --port 8080 .

第一个命令将生成三个文件:一个WASM模块,一个显示代码的HTML文件以及一个设置模块的JS文件,并负责运行所需的所有内容。 WASM = 1向Emscripten表明我们想要生成一个WASM模块,而不是一个asm.js文件。
webassembly.png
您还可以使用--shell-file选项在自定义模板中输出代码。 Emscripten SDK安装包含此位置的基本模板(esmdk-folder)/emscripten/incoming/src/shell_minimal.html。 将该文件复制到您的项目中并根据需要进行调整(例如,添加其余的JS代码)。

# We renamed it WebAssemblyTemplate.html
emcc -o WebAssemblyExample.html WebAssemblyExample.c -O3 -s WASM=1 --shell-file WebAssemblyTemplate.html

你也可以直接输出一个JS文件,但目前不推荐。 那是因为你需要代码来处理内存分配,内存泄漏等低级问题。

最后的目标是使加载WebAssembly模块的过程变得简单,就是使用<script type ='module'> HTML代码加载JavaScript代码,但是我们还没有加载。

C和JavaScript之间的互相操作
C和JavaScript之间的互相操作是Emscripten的一个问题。 你必须做的第一件事是包含emscripten的头文件。

#include <emscripten.h>

调用JavaScript的简单方法就是调用函数emscripten_run_script:

// it is equivalent to call eval() in JavaScript
emscripten_run_script("alert('hello')");

从JavaScript调用C函数稍微复杂一些。 首先,您必须从C / C ++代码中提供它,因为默认情况下Emscripten不能使用除主函数之外的所有C函数。 所以,您必须将修饰符EMSCRIPTEN_KEEP_ALIVE添加到您要在JavaScript中使用的所有函数中。

int EMSCRIPTEN_KEEPALIVE factorial(int n) {
  if (n == 0)
    return 1;
  else
    return n * factorial(n-1);
}

如果你用C ++编写的话,记得把你希望在extern'C'块中提供的任何函数放在一起,为了避免C ++弄错函数的名字(这是C ++所做的事,它不是WebAssembly或Emscripten的错误)。

其次,您必须使用NO_EXIT_RUNTIME选项来编译WebAssembly模块,这样可以避免在main函数的退出时关闭运行时,从而无法从JavaScript调用C代码。

emcc -o WebAssemblyExample.html WebAssemblyExample.c -O3 -s WASM=1 -s NO_EXIT_RUNTIME=1 --shell-file WebAssemblyTemplate.html

第三,你不能直接调用你的C函数,但是你必须使用下面的语法。

Module.ccall('factorial', // name of C function
             'number', // return type
             ['number'], // argument types
             [4] // arguments
);

类型可以是三个之一:数字,字符串和数组。

如果您需要在JavaScript代码中多次使用该函数,则可以使用cwrap函数来包装它。

factorial = Module.cwrap('factorial', 'number', ['number'])
factorial(4);

您可以轻松地在控制台中尝试。
webssembly_console.png

结语
我们已经看到了WebAssembly的简短介绍:它是什么,为什么你应该关心以及如何使用它。 它将成为网络进一步发展的一个很好的平台:它将使网络的开发变得更容易,更高效。

它的发展得到了Mozilla,微软,Google和苹果的支持。 对工具的关注是WebAssembly重要性的另一个证明:它将快速改变Web。

您现在可以使用WebAssembly,并在MDN网站上查看更深入的文档。 如果你有兴趣了解更多关于格式的细节,你可以在官方网站上阅读。 您也可以查看Emscripten文档来了解与JavaScript和C / C ++代码之间的互相操作相关的问题。