目录

WebAssembly

WebAssembly 是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如 C / C ++等语言提供一个编译目标,以便它们可以在 Web 上运行。它也被设计为可以与 JavaScript 共存,允许两者一起工作。

$ git clone https://github.com/juj/emsdk.git
$ cd emsdk
$ ./emsdk install sdk-incoming-64bit binaryen-master-64bit
$ ./emsdk activate sdk-incoming-64bit binaryen-master-64bit

# 使用最新的代码
$ ./emsdk install latest
$ ./emsdk activate latest

但是因为llvm需要连接github进行下载,常常会失败,因此需要使用mirror, 修改emsdk_manifest.json,找到https://github.com/llvm/llvm-project.git,修改为 https://mirrors.tuna.tsinghua.edu.cn/git/llvm-project.git,然后在执行下编译.

工具链编译结束,导入环境变量

source ./emsdk_env.sh
#include <stdio.h>
int main(int argc, char *argv[])
{
  printf("Hello world\r\n");
  return 0;
}
#include <iostream>
int main(int argc, char *argv[])
{
  std::cout << "Hello world\r\n" << std::endl;
  return 0;
}

执行编译

emcc hello.c -s WASM=1 -o hello.html # 执行编译
emrun --no_browser --port 8080 .     # 运行

使用-o hello.html编译后,除了hello.html之外,还会生成hello.jshello.wasm两个文件:

  • hello.js: 加载并运行wasm模块的胶水代码
  • hello.wasm: 编译生成的二进制模块

hugo是静态网页生成器,不适合直接使用生成的hello.html,只需要将hello.jshello.wasm复制到hugo的static目录,然后在文章中通过wasm shortcode加载:

$ mkdir -p static/wasm
$ cp hello.js hello.wasm static/wasm/
{{< wasm "hello" >}}

如果需要自定义存放目录,可以传递第二个参数指定:

{{< wasm "hello" "lib" >}}

上面的写法会生成<script src="/lib/hello.js" defer></script>.

wasm shortcode会生成<script src="/wasm/hello.js" defer></script>标签,等价于直接在文章中插入:

<script src="/wasm/hello.js" defer></script>

hello.js会自动加载同目录下的hello.wasm并执行main函数,printf的输出会显示在浏览器的控制台中.

如果只需要在js中调用某些函数,而不是直接执行main,可以在编译时导出指定的函数:

$ emcc hello.c -s WASM=1 -s EXPORTED_FUNCTIONS='["_add"]' -o hello.js

然后在js代码中通过Module调用:

Module.onRuntimeInitialized = function() {
    console.log(Module._add(1, 2));
};

注意: 被导出的函数需要保证不被优化删除,可以使用EMSCRIPTEN_KEEPALIVE修饰.

相关内容