WebAssembly核心编程[1]:wasm模块实例化的N种方式

当我们在一个Web应用中使用WebAssembly,最终的目的要么是执行wasm模块的入口程序(通过start指令指定的函数),要么是调用其导出的函数,这一切的前提需要创建一个通过WebAssembly.Instance对象表示的wasm模块实例(源代码)。

一、wasm模块实例化总体流程

虽然编程模式多种多样,但是wasm模块的实例化总体采用如下的流程:

  • 步骤一:下载wasm模块文件;

  • 步骤二:解析文件并创建通过WebAssembly.Module类型表示的wasm模块;

  • 步骤三:根据wasm模块,结合提供的导入对象,创建通过WebAssembly.Instance类型表示的模块实例。

二、利用WebAssembly.Module创建实例

我们照例通过一个简单的实例来演示针对wasm模块加载和模块实例创建的各种编程模式。我们首先利用WebAssembly Text Format(WAT)形式定义如下一个wasm程序,定义的文件名为app.wat。如代码所示,我们定义了一个用于输出指定浮点数(i64)绝对值的导出函数absolute。绝对值通过f64.abs指令计算,具体得输出则通过导入的print函数完成。

(module(func $print (import "imports" "print") (param $op f64) (param $result f64))(func (export "absolute") (param $op f64)(local.get $op)(f64.abs (local.get $op))(call $print))
)

我们通过指定wat2wasm (源代码压缩包种提供了对应的.exe)命令(wat2wasm app.wat –o app.wasm)编译app.wat并生成app.wasm后,定义如下这个index.html页面,作为宿主程序的JavaScript脚本完全按照上面所示的步骤完成了针对wasm模块实例的创建。

<html><head></head><body><div id="container"></div><script>var print = (op, result) => document.getElementById("container").innerText = `abs(${op}) = ${result}`;fetch("app.wasm").then((response) => response.arrayBuffer()).then(bytes => {var module = new WebAssembly.Module(bytes);var instance = new WebAssembly.Instance(module, {"imports":{"print": print}});instance.exports.absolute(-3.14);})</script></body>
</html>

具体来说,我们调用fetch函数将app.wasm文件下载下来后,我们将获得的字节内容作为参数调用构建函数创建了一个WebAssembly.Module对象。然后将这个Module对象和创建的导入对象({"imports":{"print": print}})作为参数调用构造函数创建了一个WebAssembly.Instance对象,该对象正是我们需要的wasm模块实例。我们从模块实例中提取并执行导出的absolute函数。导入的print函数会将绝对值计算表达式以如下的形式输出到页面中。

image

除了调用构造函数以同步(阻塞)的方式根据WebAssembly.Module对象创建WebAssembly.Instance对象外,我们还可以调用WebAssembly.instantiate静态方法以异步的方式“激活”wasm模块实例,它返回一个Promise<WebAssembly.Instance>对象。

var print = (op, result) => document.getElementById("container").innerText = `abs(${op}) = ${result}`;
fetch("app.wasm").then((response) => response.arrayBuffer()).then(bytes => {var module = new WebAssembly.Module(bytes);return WebAssembly.instantiate(module, { "imports": { "print": print } });}).then(instance => instance.exports.absolute(-3.14));

三、通过字节内容创建创建实例

静态方法WebAssembly.instantiate还提供了另一个重载,我们可以直接指定下载wasm模块文件得到的字节内容作为参数。这个重载返回一个Promise<WebAssembly.WebAssemblyInstantiatedSource>对象,WebAssemblyInstantiatedSource对象的instance属性返回的正是我们需要的wasm模块实例。

var print = (op, result) => document.getElementById("container").innerText = `abs(${op}) = ${result}`;
fetch("app.wasm").then((response) => response.arrayBuffer()).then(bytes => WebAssembly.instantiate(bytes, {"imports":{"print": print}})).then(result =>result.instance.exports.absolute(-3.14));

四、利用XMLHttpRequest加载wasm模块

fetch函数是我们推荐的用于下载wasm模块文件的方式,不过我们一定义要使用传统的XMLHttpRequest对象也未尝不可。上面的三种激活wasm模块实例的方式可以采用如下的形式来实现。

var print = (op, result) => document.getElementById("container").innerText = `abs(${op}) = ${result}`;
const request = new XMLHttpRequest();
request.open("GET", "app.wasm");
request.responseType = "arraybuffer";
request.send();request.onload = () => {var bytes = request.response;var module = new WebAssembly.Module(bytes);var instance = new WebAssembly.Instance(module, {"imports":{"print": print}});instance.exports.absolute(-3.14);
};

上面演示的利用创建的WebAssembly.Module对象和导入对象调用构造函数创建WebAssembly.Instance的同步形式。下面则是将二者作为参数调用静态方式WebAssembly.instantiate以异步方式激活wasm模块实例的方式。

var print = (op, result) => document.getElementById("container").innerText = `abs(${op}) = ${result}`;
const request = new XMLHttpRequest();
request.open("GET", "app.wasm");
request.responseType = "arraybuffer";
request.send();request.onload = () => {var bytes = request.response;WebAssembly.instantiate(request.response, {"imports":{"print": print}}).then(result => result.instance.exports.absolute(-3.14));
};

下面演示WebAssembly.instantiate静态方法的另一个重载。

var print = (op, result) => document.getElementById("container").innerText = `abs(${op}) = ${result}`;
const request = new XMLHttpRequest();
request.open("GET", "app.wasm");
request.responseType = "arraybuffer";
request.send();request.onload = () => {var bytes = request.response;WebAssembly.instantiate(request.response, {"imports":{"print": print}}).then(result => result.instance.exports.absolute(-3.14));
};

五、极简编程方式

其实我们有“一步到位”的方式,那就是按照如下的形式执行静态方法WebAssembly.instantiateStreaming。该方法的第一个参数用于提供下载.wasm模块文件的PromiseLike<Response>对象,第二个参数则用于指定导入对象。该方法同样返回一个Promise<WebAssembly.WebAssemblyInstantiatedSource>对象,WebAssemblyInstantiatedSource的instance属性返回的正是我们所需的wasm模块实例。

var print = (op, result) => document.getElementById("container").innerText = `abs(${op}) = ${result}`;
WebAssembly.instantiateStreaming(fetch("app.wasm"), {"imports":{"print": print}}).then(result => result.instance.exports.absolute(-3.14))

文章转载自:Artech

原文链接:https://www.cnblogs.com/artech/p/17994560/wasm_loading

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/659592.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

远程教育:低代码在教育技术领域的重塑之力

新冠肺炎大流行对世界各地的行业产生了影响&#xff0c;其中一些行业的影响远远超过其他行业。食品、零售、供应链、娱乐和航空业是受影响最大的行业&#xff0c;为确保不间断运营&#xff0c;这引发了一场数字革命。相信&#xff0c;这种数字化的采用将长期保持下去&#xff0…

STM32—系统定时器

1.SysTick简介 SysTick是一种系统定时器&#xff0c;可以用于实现操作系统、任务调度、时钟管理等功能。它通常集成在微控制器中&#xff0c;并且是硬件实现的&#xff0c;具有高精度和可靠性。 在ARM Cortex-M处理器中&#xff0c;SysTick定时器可以配置为计数器模式或外部时…

力扣hot100 数组中的第K个最大元素 堆 三路划分

Problem: 215. 数组中的第K个最大元素 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn) Code class Solution {public int findKthLargest(int[] nums, int k…

5种改进生产 Web 应用服务器设置的方法

简介 一旦你的应用程序在云服务器环境中运行起来&#xff0c;你可能会想知道如何改进你的服务器环境&#xff0c;使其从“能用”跃升到一个完整的生产环境。本文将帮助你开始规划和实施生产环境&#xff0c;通过在云服务器环境中创建一个“生产环境”的宽泛定义&#xff0c;并…

Java:搭建eladmin复习mvn、springboot、vue等

目录 1.源码平台后端&#xff1a; 2.源码平台前端&#xff1a; 3.操作系统&#xff1a;centos7.9 4.mysql:5.7.x 安装 5.redis:5.0.X 6.maven&#xff1a;3.8 7.java:1.8&#xff1a; 8.nodejs:16.x 9.通过mvn打包eladmin后端 10.npm打包前端项目进行部署 11.访问测试…

电子文件归档管理有哪些方法

电子文件归档管理有以下几种方法&#xff1a; 1. 按文件类型归档&#xff1a;将电子文件根据文件类型进行归档管理&#xff0c;如将所有的文档文件放在一个文件夹中&#xff0c;所有的图像文件放在另一个文件夹中&#xff0c;便于管理和查找。 2. 按时间归档&#xff1a;将电子…

力扣经典题目:循环队列

1.虽然是循环队列&#xff0c;但需要提供一个队列为满的情况&#xff0c;所以&#xff0c;要设立一个空的队列元素&#xff0c;当最后一个元素的next指针加一等于第一个元素的时候为满 2.可以增加一个size记录元素个数&#xff0c;当size为0的时候为空&#xff0c;当size为目标…

操作股票的强化学习实现

实现一个操作股票的强化学习模型需要几个关键步骤。以下是一个基本的实现流程&#xff1a; 1. 环境设定 首先&#xff0c;我们需要定义一个环境&#xff0c;该环境会模拟股票市场的动态。环境需要至少提供以下功能&#xff1a; 重置&#xff08;Reset&#xff09;&#xff1…

晶相光电 JX-A05 车规级 200万 像素图像传感器

晶相光电推出的 JX-A05 是一款 1/2.7英寸、3.0m、90fps12bit 的车规级 200万 像素图像传感器。JX-A05 拥有三段曝光 HDR 30fps 技术&#xff0c;实现高达 120dB 的高动态范围。汽车在夜间行驶复杂多变恶劣的光线环境下&#xff0c;JX-A05 拥有优异的夜视全彩成像性能。JX-A05 具…

【HTML 基础】表单标签

文章目录 1. <form>2. <input>3. <select> 和 <option>4. <textarea>5. <button>结语 HTML 表单是互联网上交互性最强的元素之一&#xff0c;它允许用户输入、选择和提交数据。在这篇博客中&#xff0c;我们将介绍 HTML 中一些关键的表单标…

如何写论文——(8)用故事逻辑写文献综述

文献综述一般出现在论文的引言部分&#xff0c;用来支撑自己研究目标的合理性 一、情景Situation 挑出文献中最不具有争议&#xff0c;读者最容易认同的部分来入手 二、冲突Conflication 起伏的开始&#xff0c;是一个显然的挑战或者一个通过分析文献才能发现的潜在的危险或…

brpc之单例

简介 GetLeakySingleton是单例模板类,线程安全的 GetLeakySingleton template <typename T> class GetLeakySingleton { public:static butil::subtle::AtomicWord g_leaky_singleton_untyped;static pthread_once_t g_create_leaky_singleton_once;static void creat…

【AI_Design】Midjourney技巧进阶

目录 参考链接 参考链接 [Midjourney]垫图的5种进阶技巧&#xff0c;让你的生图更精准

MySQL必看表设计经验汇总-下(精华版)

本内容一共分上下两篇 上&#xff1a;MySQL必看表设计经验汇总-上(精华版)-CSDN博客 下&#xff1a;MySQL必看表设计经验汇总-下(精华版)-CSDN博客 目录 7.定义字段尽可能not null 8.合理添加索引 9.不需要严格遵守3NF&#xff0c;通过业务字段冗余来减少表关联 11.避免使用…

使用VScode远程连接Ubuntu

君衍. 一、环境准备二、配置VScode三、远程连接Ubuntu 平常远程连接服务器的工具有很多&#xff0c;比如Moba、Xshell、putty、甚至CRT都可以进行远程连接服务器&#xff0c;但是他们的本质是相同的&#xff0c;都是使用ssh来进行远程连接。 这里我们之所以要使用VScode远程连接…

Hadoop-MapReduce-源码跟读-ReduceTask阶段篇

一、源码下载 下面是hadoop官方源码下载地址&#xff0c;我下载的是hadoop-3.2.4&#xff0c;那就一起来看下吧 Index of /dist/hadoop/core 二、Reducer类 我们先看下我们写的reduce所继承的Reducer类 public class Reducer<KEYIN,VALUEIN,KEYOUT,VALUEOUT> {/*** 传…

Spring Boot 中操作 Bean 的生命周期

1.InitializingBean和DisposableBean InitializingBean接口提供了afterPropertiesSet方法&#xff0c;用于在bean的属性设置好之后调用&#xff1b; DisposableBean接口提供了destroy方法&#xff0c;用于在bean销毁之后调用&#xff1b; public class TestComponent implem…

C语言-算法-搜索剪枝与记忆化搜索

Function 题目描述 对于一个递归函数 w ( a , b , c ) w(a,b,c) w(a,b,c) 如果 a ≤ 0 a \le 0 a≤0 或 b ≤ 0 b \le 0 b≤0 或 c ≤ 0 c \le 0 c≤0 就返回值$ 1$。如果 a > 20 a>20 a>20 或 b > 20 b>20 b>20 或 c > 20 c>20 c>20 就返…

用 CanvasKit 实现超级丝滑的原神地图(已开源)!!!

首先给大家送上预览地址&#xff1a; 官网地址&#xff1a;https://webstatic.mihoyo.com/ys/app/interactive-map/index.html canvaskit地址&#xff1a;http://106.55.55.247/ky-genshin-map/ 为什么 canvaskit 有如此高的性能&#xff1f; 第一个问题&#xff0c;官方网页…

算法训练营day19,二叉树8-2

type TreeNode struct { Val int Left *TreeNode Right *TreeNode } 450. 删除二叉搜索树中的节点 /*本题比较难&#xff0c;删除节点要分五种情况考虑 1.没有找到要删除的节点 2.找到要删除的节点是叶子节点 3.找到要删除的节点&#xff0c;左指针不为空&#xff0c;…