WebAssembly入门笔记[4]:利用Global传递全局变量
利用WebAssembly的导入导出功能可以灵活地实现宿主JavaScript程序与加载的单个wasm模块之间的交互,那么如何在宿主程序与多个wasm之间传递和共享数据呢?这就需要使用到Global这个重要的对象了。
一、数值类型全局变量
二、将JavaScript函数设置为全局变量
三、利用全局变量处理字符串
一、数值类型全局变量
Global全局变量支持多种值类型,包括数组(i32/i64和f32/f64)、向量和引用类型(externref和funcref)。下面的实例利用Global提供了全局计数的功能。在WebAssembly Text Format (WAT)文件app.wat中,我们从宿主JavaScript应用中导入了一个i32类型的可读写(mut表示可以修改)的全局变量,导入路径为“imports.counter”,我们将其命名为$counter。在用于自增的导出函数increment中,我们通过执行global.get指令读取全局变量的值,并将其加1之后,执行global.set指令对全局变量重新赋值。
(module
(global $counter (import "imports" "counter") (mut i32))
(func (export "increment")
(i32.add (global.get $counter) (i32.const 1))
(global.set $counter)
)
)
在index.html文件中,我们在页面中添加了一个“Increment”按钮,并利用一个<span>显式计算器当前的值。JavaScript脚本通过调用WebAssembly.Global构造函数将代表全局变量的Global对象创建出来后,调用WebAssembly.instantiateStreaming加载app.wat编译生成的app.wasm模块文件,并将此Global对象包含在导入对象中。
<html>
<head></head>
<body>
<span id="counter">0</span>
<button id="btnInc">Increment</button>
<script>
const globalCounter = new WebAssembly.Global({ value: "i32", mutable: true }, 0);
WebAssembly
.instantiateStreaming(fetch("app.wasm"), {"imports":{"counter":globalCounter}})
.then(results => {
document.getElementById("btnInc").onclick = ()=>{
results.instance.exports.increment();
document.getElementById("counter").innerText = globalCounter.value;
};
});
</script>
</body>
</html>
wasm模块充成功导入后,我们注册了按钮的click事件,使之在调用导出的increment函数后,重新刷新计数器的值。如下图所示,针对“Increment”的每次点击都将计数器加1(源代码)。

二、将JavaScript函数设置为全局变量
除了四种数值类型,Global还支持两种引用类型externref和funcref,利用externref可以将宿主应用提供的任意JavaScript对象作为全局变量,下面的实例演示利用这种方式实现了与类似的功能。如下面的代码片段所示,新的app.wat导入了一个类型为externref的全局变量,对应着数组应用提供的一个用来对全局计数自增的Javascript函数。
(module
(func $apply (import "imports" "apply") (param externref))
(global $increment (import "imports" "increment") externref)
(func $main
(call $apply (global.get $increment))
)
(start $main)
)
由于JavaScript函数的引用在.wasm模块中并不能直接执行,所以我们不得不导入一个apply函数“回传”到宿主应用中执行。我们修改的应用用来统计导入的wasm模块的数量,所以我们在入口函数$main中利用apply调用了全局变量$increment引用的函数。
在index.html,我们在页面中添加了一个“Load”按钮来加载app.wat编译生成的app.wasm模块。JavaScript脚本利用counter变量表示加载的wasm模块数量,并通过调用WebAssembly.Global构造函数创建了rexternref类型的全局变量,其值为一个对counter自增的函数。
<html>
<head></head>
<body>
<p>There are totally <span id="counter" style= "color: read”>0</span> wasm modules loaded. </p>
<button id="btnLoad">Load</button>
<script>
var counter = 0;
const globalIncrement = new WebAssembly.Global({ value: "externref"}, ()=>counter++);
var apply = func => func();
document.getElementById("btnLoad").onclick = ()=>{
WebAssembly
.instantiateStreaming(fetch("app.wasm"), {"imports":{"increment":globalIncrement,"apply": apply }})
.then(_=>{
document.getElementById("counter").innerText = counter;
})
};
</script>
</body>
</html>
我们将这个Global对象包含到导入的对象中,并在导入成功后刷新显式的计数器,所以程序运行后将会显式当前加载的wasm模块数量(源代码)。

三、利用全局变量处理字符串
WebAssembly目前并没有提供针对字符串类型的直接支持,而是单纯地将其作为字节序列看到。目前字符串在宿主程序与wasm模块之间的传递只有通过Memory来实现。由于Javascript具有处理字符串的能力,wasm模块可以将字符串作为externref回传到宿主程序进行处理。在接下来演示的程序中,我们在app.wat中定义一个“字符类型(实际上是externref类型)”的全局变量,导出的greet函数通过调用导入的print函数将其输出。
(module
(func $print (import "imports" "print") (param externref))
(global $message (import "imports" "message") (mut externref))
(func (export "greet")
(call $print (global.get $message))
)
)
在index.html中,我们在页面上放置了三个按钮,让它们在命名为“greet”的<div>中分别显示“Good Morning”、“Good Afternoon”和“Good Evening”三条问候语。具体的问候语通过函数print输出,它的参数就是代表输出文本的字符串。
<html>
<head></head>
<body>
<div id="greet"></div>
<button id="btnMorning">Morning</button>
<button id="btnAfternoon">Afternoon</button>
<button id="btnEvening">Evening</button>
<script>
var print = (msg) => {
console.log(msg);
document.getElementById("greet").innerText = msg;
}
const globalMsg = new WebAssembly.Global({ value: "externref", mutable: true }, "Good Morning!");
console.log(globalMsg.value);
WebAssembly
.instantiateStreaming(fetch("app.wasm"), {"imports":{"message":globalMsg, "print":print}})
.then(results => {
var greet = results.instance.exports.greet;
console.log(greet);
document.getElementById("btnMorning").onclick = ()=>{
globalMsg.value = "Good Morning!";
greet();
};
document.getElementById("btnAfternoon").onclick = ()=>{
globalMsg.value = "Good Afternoon!";
greet();
};
document.getElementById("btnEvening").onclick = ()=>{
globalMsg.value = "Good Evening!";
greet();
};
});
</script>
</body>
</html>
我们定义了一个externref类型的Global对象来引用带输出的问候语文本,并在加载app.wasm木块使将其包含到导入对象中。三个按钮的click事件处理程序通过调用导出的greet函数输出对于的问候语,但是在调用此函数之前会对Global对象进行相应的赋值(源代码)。

WebAssembly入门笔记[4]:利用Global传递全局变量的更多相关文章
- Blazor入门笔记(6)-组件间通信
1.环境 VS2019 16.5.1.NET Core SDK 3.1.200Blazor WebAssembly Templates 3.2.0-preview2.20160.5 2.简介 在使用B ...
- redis入门笔记(2)
redis入门笔记(2) 上篇文章介绍了redis的基本情况和支持的数据类型,本篇文章将介绍redis持久化.主从复制.简单的事务支持及发布订阅功能. 持久化 •redis是一个支持持久化的内存数据库 ...
- MySQL入门笔记
MySQL入门笔记 版本选择: 5.x.20 以上版本比较稳定 一.MySQL的三种安装方式: 安装MySQL的方式常见的有三种: · rpm包形式 · 通用二进制 ...
- MySQL入门笔记(二)
MySQL的数据类型.数据库操作.针对单表的操作以及简单的记录操作可参考:MySQL入门笔记(一) 五.子查询 子查询可简单地理解为查询中的查询,即子查询外部必然还有一层查询,并且这里的查询并非仅 ...
- redis入门笔记
redis入门笔记 参考redis实战手册 1. Redis在windows下安装 下载地址:https://github.com/MSOpenTech/redis/tags 安装Redis 1.1. ...
- golang微服务框架go-micro 入门笔记2.4 go-micro service解读
本章节阐述go-micro 服务发现原理 go-micro架构 下图来自go-micro官方 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go- ...
- [Java入门笔记] 面向对象编程基础(二):方法详解
什么是方法? 简介 在上一篇的blog中,我们知道了方法是类中的一个组成部分,是类或对象的行为特征的抽象. 无论是从语法和功能上来看,方法都有点类似与函数.但是,方法与传统的函数还是有着不同之处: 在 ...
- React.js入门笔记
# React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...
- unity入门笔记
我于2010年4月1日硕士毕业加入完美时空, 至今5年整.刚刚从一家公司的微端(就是端游技术+页游思想, 具体点就是c++开发, directX渲染, 资源采取所需才会下载)项目的前端主程职位离职, ...
- System Generator入门笔记
System Generator入门笔记 [CPLD/FPGA] 发布时间:2010-04-08 23:02:09 System Generator是Xilinx公司进行数字信号处理开发的一种设计 ...
随机推荐
- JSP | JSP 动作详解
原作者为 RioTian@cnblogs, 本作品采用 CC 4.0 BY 进行许可,转载请注明出处. 本篇学习自:C语言中文网,部分内容转载仅供学习使用. \[QAQ \] JSP 动作利用 XML ...
- vue 使用print.js实现前端打印功能
https://blog.csdn.net/cccdf_jjj/article/details/99563682 插件vue-print-nb实现前端打印当前页面功能 https://blog.csd ...
- C#排序算法6:快速排序
快速排序由C. A. R. Hoare在1960年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分 ...
- [kubernetes]服务健康检查
前言 进程在运行,但是不代表应用是正常的,对此pod提供的探针可用来检测容器内的应用是否正常.k8s对pod的健康状态可以通过三类探针来检查:LivenessProbe.ReadinessProbe和 ...
- 2023 SHCTF-校外赛道 MISC WP
WEEK1 请对我使用社工吧 提示:k1sme4的朋友考到了一所在k1sme4家附近的大学,一天,k1sme4的朋友去了学校对面的商场玩,并给k1sme4拍了一张照片,你能找到他的学校吗? flag格 ...
- [转帖]TiDB修改配置参数
https://www.jianshu.com/p/2ecdb4642579 在TiDB 中,"修改配置参数"似乎是个不精准的说法,它实际包含了以下内容: 修改 TiDB 的系统变 ...
- [转帖]Kubernetes-15:一文详解Pod、Node调度规则(亲和性、污点、容忍、固定节点)
https://www.cnblogs.com/v-fan/p/13609124.html Kubernetes Pod调度说明 简介 Scheduler 是 Kubernetes 的调度器,主要任务 ...
- [转帖]企业nginx简单配置
https://www.jianshu.com/p/6a3e298b31be 第五章 企业简单应用 网站访问方式 1.基于域名访问www.baidu.com 基于IP地址访问172.16.1.7配置文 ...
- [转帖]Linux命令拾遗-top中的%nice是啥
https://www.cnblogs.com/codelogs/p/16060663.html 简介# 这是Linux命令拾遗系列的第八篇,本篇主要介绍top命令中nice%这个指标的含义以及进程优 ...
- [转帖]Nginx(3):上手Nginx,从配置文件开始
https://cloud.tencent.com/developer/article/1886147?areaSource=&traceId= 其实吧,我配置 tcp 负载均衡的时候也就 ...