我们相信:世界是美好的,你是我也是。 来玩一下解压小游戏吧!

本文不涉及wasm文件的编译,这里假设通过某种编程语言的编译手段,已经得到了一个release.wasm文件。那么,如何使用这个wasm文件里面的导出函数呢?这就是本文要讨论的问题。

苏南大叔:浏览器/Node环境,使用wasm文件的几种方式 - wasm文件的不同使用姿势
浏览器/Node环境,使用wasm文件的几种方式(图4-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。测试环境:win10node@20.18.0

前文回顾

如果手里没有合适的标的物release.wasm文件,可以参考上一篇文章,拿到一个导出函数为add(a,b)add2(a,b)wasm文件。

如果拿到的是个完全未知的.wasm文件,可以参考下面的文章,进行导出函数的分析。

本文的思路上很简单,就是加载.wasm,然后解析.wasm,然后执行导出函数。

  • 对于不同的使用环境,技术细节是有所不同的。主要的区别就在于如何加载.wasm
  • 而关于模块加载importrequire的区别,这里并没有涉及到。因为是通过WebAssembly.instantiate()来导入的。

纯node环境

在纯node环境下,是使用fs模块来加载.wasm文件的。范例t.js如下:

const fs = require('fs');
const wasmBuffer = fs.readFileSync('release.wasm');
WebAssembly.instantiate(wasmBuffer).then(wasmModule => {
    const { add, add2 } = wasmModule.instance.exports;
    console.log(add(1, 2));  // 输出 3
    console.log(add2(3, 4)); // 输出 8
});

苏南大叔:浏览器/Node环境,使用wasm文件的几种方式 - node环境加载wasm
浏览器/Node环境,使用wasm文件的几种方式(图4-2)

当然,也可以改成import('fs')。范例t.mjs【注意,这里是.mjs文件】如下:

import fs from 'fs';
const wasmBuffer = fs.readFileSync('release.wasm');
WebAssembly.instantiate(wasmBuffer).then(wasmModule => {
    const { add, add2 } = wasmModule.instance.exports;
    console.log(add(1, 2));  // 输出 3
    console.log(add2(3, 4)); // 输出 8
});

浏览器环境

下面的代码,只能在浏览器环境下执行。因为fetch()函数并不支持file协议。注意配置容器及mime映射。

fetch('./release.wasm')
.then(rep => rep.arrayBuffer())                  // 转 ArrayBuffer
.then(bytes => WebAssembly.compile(bytes))       // 编译为 module 对象
.then(module => WebAssembly.instantiate(module)) // 创建 instance 对象
.then(instance => {
    const { add, add2 } = instance.exports;
    console.log(add(1, 2));
    console.log(add2(1, 3));
});

苏南大叔:浏览器/Node环境,使用wasm文件的几种方式 - 浏览器执行代码
浏览器/Node环境,使用wasm文件的几种方式(图4-3)

WebAssembly.instantiateStreaming(fetch('./release.wasm')).then(res => {
    const { module, instance } = res;
    const { add, add2 } = instance.exports;
    console.log(add(1, 2));
    console.log(add2(1, 3));
});
虽然现在的纯node环境下,也有fetch函数。但是,这个fetch()phpfile_get_contents()还是有所区别的。它不支持读取本地,只支持读取网络文件。

但是,可能会碰到下面的报错问题。

mime 映射

报错信息如下:

Uncaught (in promise) TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'.

可能的解决方案:

苏南大叔:浏览器/Node环境,使用wasm文件的几种方式 - 配置mime
浏览器/Node环境,使用wasm文件的几种方式(图4-4)

另外,如果是测试的话,直接用python起一个容器,是最简单的。不用mime映射:

python -m http.server 8080

跨域

已拦截跨源请求:同源策略禁止读取位于 file:///C:/Users/sunan/Desktop/t/release.wasm 的远程资源。(原因:CORS 请求不是 http)。

或者:

Access to fetch at 'file:///C:/Users/sunan/Desktop/t/release.wasm' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: chrome, chrome-extension, chrome-untrusted, data, http, https, isolated-app.

解决方案:不要双击打开,请放置到容器(例如nginx)内,然后访问网络地址。

相关文档

参考文章:

结语

更多苏南大叔的wasm经验文章,请点击下面的链接:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   wasm