持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
上一篇文章我们了解了WebAssembly的基本概念和使用场景。但是我们只是直接调用了API,对浏览器中的WebAssemblyAPI还不是很了解。
那么接下来看一下浏览器中WebAssemblyAPI的用法。
浏览器加载wasm流程
我们从上一节的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编译
1.compile
WebAssembly.compile的作用就是将从网络获取回来的wsam二进制码编译成Module,它只接收一个byte的参数。
WebAssembly.compile(bytes)
2.instantiate & Instance
instantiate 和 Instance 都是可以实例化模块,方法接收两个参数:Module和imports
const moduleA = WebAssembly.instantiate(module, imports);
const moduleB = new WebAssembly.Instance(module, imports);
- Module: 从
WebAssymbly.compile编译出来的模块。 - imports: 这个模块需要引入的函数,imports非常重要,这个关乎到我们的Module能不能正常编译成功。
再来写一个需要分配内存的方法
#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模块中能找到。
3. instantiateStreaming
instantiateStreaming方法是toArrayBuffer,compile和instantiate的集合,一个方法就包含这三步
const module = WebAssembly.instantiateStreaming(fetch('xxx.wsam'), imports);
4.Memory
Memory用于表示编译模块使用的堆,在JS中他是一种可调整大小的ArrayBuffer的形式存在的。上文中也可以看到,在声明一个模块都需要import一个内存实例到模块中。
const mem = new WebAssembly.Memory({
// 初始化内存
initial: 1,
// 最大内存
maximum: 100,
// 内存是否可共享
share: true,
})
initial,maximum内存的单位是WebAssembly pages,固定每页是64KB。最大可支持6.4MB
总结
本小节主要详细介绍了WebAssymbly的主要API和编译流程 往期回顾:
- 初探WebAssembly
- WebAssembly由浅入深