WebAssembly.instantiate()
该函数是用于编译和实例化 WebAssembly 代码的主要API。 此功能有两个重载:
主要重载采用 WebAssembly 二进制代码,以类型化的数组或 ArrayBuffer 的形式,并在一个步骤中同时执行编译和实例化。resolve 的 Promise 为编译的
WebAssembly.Module及其第一个WebAssembly.Instance。次要重载采用已编译的
WebAssembly.Module,并 resolve 一个解析为该模块的实例的 Promise。 如果模块已经从高速缓存中进行了编译或检索,这个重载是很有用的。
主要重载 - 采用二进制代码
用法:
Promise<ResultObject> WebAssembly.instantiate(bufferSource, importObject);参数:
bufferSource:一个包含要编译的.wasm模块的二进制代码的类型数组或ArrayBuffer。importObject:包含要导入到新创建的实例中的值的对象,例如函数或WebAssembly.Memory对象。每个声明导入的编译模块必须有一个匹配的属性,否则会抛出一个WebAssembly.LinkError。返回值
resolve:一个包含以下两个字段的 ResultObject 的 Promise.module:表示编译的 WebAssembly 模块的WebAssembly.Module对象。 此模块可以再次实例化,通过postMessage()或在IndexedDB中缓存 共享。instance:包含所有导出的 WebAssembly 函数的WebAssembly.Instance对象。注意:
如果任一参数不是正确的类型或结构,则抛出 TypeError。
如果操作失败,Promise 会 reject 一个
WebAssembly.CompileError、WebAssembly.LinkError或WebAssembly.RuntimeError,具体取决于失败的原因。
二次重载 - 采用模块对象实例
用法:
Promise<WebAssembly.Instance> WebAssembly.instantiate(module, importObject);参数:
module:要实例化的WebAssembly.Module对象。importObjec(可选):包含要导入到新创建的实例中的值的对象,例如函数或WebAssembly.Memory对象。每个声明的模块导入必须有一个匹配的属性,否则会抛出一个WebAssembly.LinkError。返回值:
resolve 一个
WebAssembly.Instance对象的 Promis。注意:
如果任一参数不是正确的类型或结构,则抛出 TypeError。
如果操作失败,Promise 会 reject 一个
WebAssembly.CompileError、WebAssembly.LinkError或WebAssembly.RuntimeError,具体取决于失败的原因。在 C 文件中通过
extern的形式导入 js 变量和函数,但是导入的变量和函数必须在对象importObjec的env属性中,因为 C 中默认extern读取的是env对象中的属性和方法。在 C++ 中函数要写在
extern "C"{}中,因为 C++ 有重载的概念,会把定义的方法名编译,前后加上字符串,函数名变得不可测,写入extern "C"{}会按照 C 的方式编译,函数名不变。
例子
主要重载
import * as fs from 'fs';
const path = './addOne.wasm';
const buffer = fs.readFileSync(path);
const importObject = {
env: {
addOne: function (arg) {
return arg + 1;
}
}
};
WebAssembly.instantiate(buffer, importObject)
.then((mod: any) => {
const result = mod.instance.exports.add(4, 5);
console.log(result);
})
结果会输出 10。在 C 中定义了 add 函数执行 js 中的 addOne 函数,同时传入了 js 传过来的两个数字相加,执行结果就是两个数字相加后再加1。
这种是直接在 WebAssembly.instantiate 中传入 wasm 的二进制代码,会直接生成 WebAssembly.instance 类型的实例化对象。下面的二次重在例子和这个例子结果一样。
二次重载:
import * as fs from 'fs';
import { EventEmitter } from 'events';
const path = './addOne.wasm';
const buffer = fs.readFileSync(path);
const emitter = new EventEmitter();
WebAssembly.compile(buffer).then(mod => emitter.emit('mod', mod));
const importObject = {
env: {
addOne: function (arg) {
return arg + 1;
}
}
};
emitter.addListener('mod', mod => {
console.log('module received from main thread');
WebAssembly.instantiate(mod, importObject)
.then((instance: any) => {
const result = instance.exports.add(4, 5);
console.log(result);
});
const exports = WebAssembly.Module.exports(mod);
console.log(exports);
})
// addOne.c
// 导入 js 函数
extern int addOne(int);
int add(int a, int b) {
return addOne(a + b);
}
这个例子和上面的主要重载一样,结果会输出 10。但是在 WebAssembly.instantiate 中传入的是一个 WebAssembly.Module 对象,而不是 wasm 的二进制代码,返回值也略有不同。