WebAssembly入门笔记[2]:利用Memory传递数据
利用灵活的“导入”和“导出”机制,WebAssembly与承载的JavaScript应用之间可以很便利地“互通有无”。《与JavaScript的交互》着重演示了如何利用函数的导入和导出实现功能的共享,接下来我们主要关注数据的传递或者共享。宗地来说,WebAssembly与宿主程序之间的数据传递主要有如下三种手段,本篇文章主要关注Memory。
- Memory:以二进制(字节)的形式传递数据;
- Table:传递类型化数据(目前只支持函数);
- Global:共享全局变量;
一、导入Memory
顾名思义,一个Memory映射一块连续的内存,应用以二进制(字节)的形式对它进行读写。Memory可以利用导入功能从宿主程序传递给WebAssembly,下面的实例演示了这样的场景:作为宿主的JavaScript应用创建一个Memory对象并写入相应的内容,然后将其导入到加载的WebAssembly模块,后者将其中的内容读出来。
如下所示的代码片段是承载WebAssembly程序的app.wat文件的内容,我们利用(memory)定义了一个导入的memory,导入路径为“imports.memory”,后面指定的参数1代表初始大小,单位为Page(64K)。接下来我们定义了四个导出函数,它们会从指定的位置(参数$index表示偏移量)读取相应长度的字节内容,并将其转换成对应的类型。具体来说,这四个函数的返回类型分别为i32、i64、f32和f64,也就是WebAssembly支持的四种数据类型。具体的读取通过执行{i32|i64|f32|f64}.load指令完成,该指令将读取位置作为唯一参数,所以我们在执行该指令之前需要执行local.get 指令将代表读取位置的$index参数压入栈中。
(module
(memory (import "imports" "memory") 1) (func (export "readAsInt32") (param $index i32) (result i32)
local.get $index
i32.load
) (func (export "readAsInt64") (param $index i32) (result i64)
local.get $index
i64.load
) (func (export "readAsSingle") (param $index i32) (result f32)
local.get $index
f32.load
) (func (export "readAsDouble") (param $index i32) (result f64)
local.get $index
f64.load
)
)
有人可能有这样的疑问,我们在执行load指令的时候为什么没有指定具体读取的Memory对象呢?这是因为目前一个WebAssembly模块只能拥有一个Memory对象,这一限制会在后续版本中解除。接下来我们依然需要执行“wat2wasm app.wat –o app.wasm”命令对app.wat文件进行编译,最终生成二进制的模块文件app.wasm。该文件在index.html页面的JavaScript脚本中被加载,index.html页面的内容如下所示。如下面的代码片段所示,我们调用构造函数WebAssembly.Memory创建了一个Memory对象,并将初始大小设置为1(Page)。我们将这个Memory对象的缓冲区(对应buffer属性)映射为一个Uint32Array数组。通过设置这个数组的前两个元素的值(123),我们相应的字节写入前8个字节。
<html>
<head></head>
<body>
<div id="container"></div>
<script>
var memory= new WebAssembly.Memory({ initial: 1 });
const array = new Uint32Array(memory.buffer);
array[0] = 123;
array[1] = 123;
WebAssembly
.instantiateStreaming(fetch("app.wasm"), {"imports":{"memory":memory}})
.then(results => {
var exports = results.instance.exports;
document.getElementById("container").innerHTML =
`<p>Int32: ${exports.readAsInt32(0)}</p>` +
`<p>Int64: ${exports.readAsInt64(0)}</p>` +
`<p>Single: ${exports.readAsSingle(0)}</p>` +
`<p>Double: ${exports.readAsDouble(0)}</p>` ;
});
</script>
</body>
</html>
我们从WebAssembly模块实例中导出前面定义的4个函数,并将针对4种不同类型读取出来的值格式化成HTML呈现出来,下图所示的就是最终的输出结果。

二、导出Memory
上面演示了如何将Memory对象从宿主应用中导入到WebAssembly模块,现在我们反其道而行,将WebAssembly模块中创建的Memory导出到宿主程序,为此我们将app.wat文件修改为如下的内容。如代码片段所示,我们利用(memory (export "memory") 1)节点定义了一个初始大小为1Page的Memory,并以名称“memory”进行导出。随后定义的导出函数initialize会将作为参数指定的两个整数写入前8个字节。针对Memory的写入通过{i32|i64|f32|f64}.store指令完成,该指令接受两个参数,第一个代表写入的位置,第二个代表写入的值。由于我们具体调用的是i32.store指令,所以在第二次调用的时候指定的写入位置是4,而不是2。
(module
(memory (export "memory") 1)
(func (export "initialize") (param $first i32) (param $second i32)
i32.const 0
local.get $first
i32.store i32.const 4
local.get $second
i32.store
)
)
在如下所示的index.html中,我们在加载WebAssembly模块“app.wasm”并得到模块实例后,调用导出的initialize函数在Memory中写入两个整数123。然后我们导出Memory对象,并将它的缓冲区映射为四种类型的数组(Uint32Array、BigUint64Array、Float32Array和Float64Array),并将第一个元素的值读取出来,这一操作与上面定义针对四个类型定义的读取函数可谓“异曲同工”。
<html>
<head></head>
<body>
<div id="container"></div>
<script>
WebAssembly
.instantiateStreaming(fetch("app.wasm"))
.then(results => {
var exports = results.instance.exports;
exports.initialize(123,123);
var buffer = exports.memory.buffer;
document.getElementById("container").innerHTML =
`<p>Int32: ${new Uint32Array(buffer)[0]}</p>`+
`<p>Int32: ${new BigUint64Array(buffer)[0]}</p>` +
`<p>Int32: ${new Float32Array(buffer)[0]}</p>`+
`<p>Int32: ${new Float64Array(buffer)[0]}</p>`;
});
</script>
</body>
</html>
我们按照相同的方式将读取出来的四个值转换成HTML进行输出,所以我们在浏览器上看到相同的结果。

WebAssembly入门笔记[2]:利用Memory传递数据的更多相关文章
- 机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据
机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据 关键字:PCA.主成分分析.降维作者:米仓山下时间:2018-11-15机器学习实战(Ma ...
- 机器学习实战 - 读书笔记(14) - 利用SVD简化数据
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第14章 - 利用SVD简化数据. 这里介绍,机器学习中的降维技术,可简化样品数据. 基 ...
- Vue.js-----轻量高效的MVVM框架(九、组件利用Props传递数据)
#使用props传递数据 html:传递普通的字符串 <h3>#使用props传递数据</h3> <div id="dr01"> <div ...
- matlab入门笔记(七):数据文件I/O
- Android开发探秘之四:利用Intent实现数据传递
在Android开发过程中,很多人都熟悉Intent,这是个用于在多个View之间共享数据的类.本节主要是继承上节,通过点选ListView中的文本,把文本中的URL加载到一个新的页面上,并且打印出来 ...
- Bundle传递数据,Handler更新UI
Bundle主要用于传递数据:它保存的数据,是以key-value(键值对)的形式存在的. Bundle经常使用在Activity之间或者线程间传递数据,传递的数据可以是boolean.byte.in ...
- Andoid Intent学习之在各个活动之间传递数据
Intent是一种运行时绑定(run-time binding)机制,它能在程序运行过程中连接两个不同的组件.通过Intent,你的程序可以向Android表达某种请求或者意愿,Android会根据意 ...
- 机器学习实战 - 读书笔记(13) - 利用PCA来简化数据
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第13章 - 利用PCA来简化数据. 这里介绍,机器学习中的降维技术,可简化样品数据. ...
- 【MVC架构】——怎样利用Json在View和Controller之间传递数据
在MVC架构中,尽管非常多东西和三层非常相似,可是也有非常大的差别.就比方传递数据.在三层架构中,传递数据就仅仅要一层返回,另外一层用同样类型的变量来接收即可了.在MVC中,事实上原理是一样的,Con ...
- [ios]利用alertView 插入数据都数据库。笔记
利用alertView 插入数据都数据库 -(void)addItemToList { UIAlertView *alter=[[UIAlertViewalloc]initWithTitle:@&qu ...
随机推荐
- 洞见商业新机,云原生数据库GaussDB让企业决策更科学
摘要:华为云GaussDB(for Redis)为数位科技打造了一个稳定可靠.高效安全.卓越性能的大数据引擎,KV存储降本80%,助力实体企业数字化转型之路走的更加稳健. 本文分享自华为云社区< ...
- 顶会VLDB'22论文解读:多元时序预测算法METRO
摘要:本文提出了一个端到端的MTS预测框架METRO.METRO的核心思想是利用多尺度动态图建模变量之间的依赖关系,考虑单尺度内信息传递和尺度间信息融合. 本文分享自华为云社区<VLDB'22 ...
- 探索SaaS产业发展新机遇|鲁班会贵安首秀圆满收官
摘要:2021年12月28日-12月29日,华为云·核心伙伴开发者训练营(第八期)-SaaS应用构建实践专场在华为贵安数据中心召开. 当前,在数字化新兴技术和数字化转型的热潮的引领下,SaaS业务应用 ...
- Error creating bean with name 'eurekaAutoServiceRegistration': Singleton bean creation not allowed while singletons
新建一个配置类 package com.cloud.client.user.feign; import org.springframework.beans.BeansException; import ...
- Spring Boot Admin 配置应用
Spring Boot Admin 监控SpringBoot 服务的运行情况 https://codecentric.github.io/spring-boot-admin/2.3.0/#spring ...
- MB51选择屏幕与报表增强
1.文档说明 如之前文档<MIGO新增页签增强>,在MIGO中增强自定义字段,那么在查询MB51时,想通过自定义字段进行筛选,并将数据展示到报表中,就需要对MB51进行增强. 此处需要说明 ...
- WPF 实现窗体鼠标事件穿透
一.窗体变透明,需要加三个属性: AllowsTransparency="True"Background="Transparent"WindowStyle=&q ...
- 高数 | Dirichlet 积分
在分析学中,Dirichlet 积分 是如下形式的 无穷限积分 \[\int_{0}^{+\infty} \frac{\sin x}{x} \mathrm{~d} x \] 它是条件收敛的,且收敛到 ...
- VIM 入门手册, (VS Code)
要想在VScode里使用Vim需要先行按照插件 安装 vim 插件 VS Code 中输入快捷键 shift + ctrl + x, 或直接打开 扩展安装导航 搜索 vim, 选择 Vim , 点击 ...
- vue网站换色功能
vue.config.js里全局配置mixin.scss: 使用: 判断 sessionStorage 中的 type 是否为空,如果为空的话,就给默认的颜色(页面初始化的颜色),如果不为空的话就将对 ...