接下来看一下浏览器中WebAssembly
API的用法。
我们从上一节的getModules
方法来看看wsam的加载流程
// 获取wsam模块
async function getModules(url, imports = {}) {
// 获取wsam文件数据
const data = await fetch(url);
// 将数据转为ArrayBuffer
const arrayBuffer = await data.arrayBuffer()
// 将ArrayBuffer编译成一个Module
const module = await WebAssembly.compile(arrayBuffer);
// 实例化Module
return WebAssembly.instantiate(module, imports);
}
可以看到,加载wsam分为三步:
从网络上获取wasm文件,并将数据转换成ArrayBuffer(注意:wsam获取严格遵循同源策略)
将ArrayBuffer二进制码编译成浏览器Module
最后实例化编译出来的Module
接下来从编译所需要的API来详细说明一下编译的流程。
WebAssembly.compile
的作用就是将从网络获取回来的wsam二进制码编译成Module,它只接收一个byte的参数。
WebAssembly.compile(bytes)
instantiate
和 Instance
都是可以实例化模块,方法接收两个参数:Module和imports
const moduleA = WebAssembly.instantiate(module, imports);
const moduleB = new WebAssembly.Instance(module, imports);
WebAssymbly.compile
编译出来的模块。再来写一个需要分配内存的方法
#include <stdlib.h>
#include <string.h>
char *helloworld()
{
char* c = (char *)malloc(14);
strcpy(c, "hello world\n");
return c;
}
可以看到,编译到wat后会出现import "env" "malloc"
的代码。这些模块是需要我们在实例化时的imports
导入的,如果在实例化中没有import这些模块,则会抛出异常。
const mem = new WenAssembly.Memory({
initial: 100,
})
const module = WebAssembly.instantiate(module, {
env: {
// malloc模块可以在 https://cdn.rawgit.com/guybedford/wasm-intro/a1e23253/7-importing-memory/memory.wasm 中找到
malloc: () => {},
memory: mem,
}
})
那么,我们又该如何找到这些模块呢?
对于这些公共模块,我们可以通过CDN找到,比如malloc模块就在memory
模块中能找到。
instantiateStreaming
方法是toArrayBuffer
,compile
和instantiate
的集合,一个方法就包含这三步
const module = WebAssembly.instantiateStreaming(fetch('xxx.wsam'), imports);
Memory用于表示编译模块使用的堆,在JS中他是一种可调整大小的ArrayBuffer
的形式存在的。上文中也可以看到,在声明一个模块都需要import一个内存实例到模块中。
const mem = new WebAssembly.Memory({
// 初始化内存
initial: 1,
// 最大内存
maximum: 100,
// 内存是否可共享
share: true,
})
initial
,maximum
内存的单位是WebAssembly pages
,固定每页是64KB
。最大可支持6.4MB