WebAssembly核心编程[3]: Module 与 Instance
WebAssembly程序总是以模块来组织,模块是基本的部署、加载和编译单元。在JavaScript编程接口中,模块通过WebAssembly.Module类型表示。WebAssembly.Module通过加载的.wasm二进制文件创建而成,它承载了描述wasm模块的元数据,类似于描述程序集的Assembly对象。WebAssembly.Module自身是只读且无状态的,有状态的是根据它结合指定的导入对象创建的模块实例,后者通过WebAssembly.Instance表示。这两个类型提供了几个核心API,解析我们就通过它们来介绍WebAssembly的这两个核心对象(源代码)。
- WebAssembly.Module.customSections
- WebAssembly.Module.imports
- WebAssembly.Module.exports
- WebAssembly.Instance.exports
一、WebAssembly.Module.customSections
我们在wasm模块中定义任意不同类型的成员,在编译生成的.wasm二进制文件中,这些成员会根据类型分布到对应的区域(section)中,确切地说“已知区域(known section)”。除了针对具体成员类型的已知区域, wasm模块还可以开辟一组命名的“自定义区域(custom section)”,静态方法WebAssembly.Module.customSections返回的ArrayBuffer指定名称的自定义区域在指定模块中的内容。目前的WebAssembly模块中大体可以定义如下11种类型的成员,对应的已知区域具有固定的代码(1-11)。
自定义区域的区域代码均为0,但是我们可以给它们进行命名。自定义区域赋予了我们在wasm模块文件中内嵌任意数据的能力。但是我们不能在.wat程序中为生成的.wasm添加自定义区域,但是如果我们在执行wat2wasm命令添加“--debug-names ”开关,编译后的.wasm中将自动添加一个名为“name”的自定义区域,该区域会将WAT程序中针对各种对象的命名(程序执行的时候不需要这些名称)存储起来,它们将会显示在我们的“调试视图”中以增强可读性。为了演示针对自定义区域的读取,我们采用WAT格式定义了如下这个程序(文件名为app.wat)。
(module
(func (import "imports" "func"))
(memory (import "imports" "memory") 1)
(table (import "imports" "table") 4 externref)
(global (import "imports" "global") (mut i32)) (func (export "func"))
(memory (export "memory") 1)
(table (export "table") 4 externref)
(global (export "global") (mut i32) (i32.const 0))
)
如上面的代码片段所示,我们导入和导出了4种类型的对象(函数、Memory、Table和Global)。由于我们使用了两个Memory对象,wat2wasm编译工具在默认情况下并不支持,所以除了添加--debug-names开关,还需要添加--enable-multi-memory开关,完整的命令行如下所示。
wat2wasm app.wat -o app.wasm --enable-multi-memory --debug-names
针对自定义区域“name”的读取按照如下的形式实现在index.html页面中:在调用fetch函数成功下app.wasm模块文件后,我们之间调用构造函数根据得到的字节内容创建了一个WebAssembly.Module对象,然后将它和区域名称“name”作为参数调用静态方法customSections。
<html>
<head></head>
<body>
<script>
fetch("app.wasm")
.then((response) => response.arrayBuffer())
.then(bytes => {
var module = new WebAssembly.Module(bytes);
var sections = WebAssembly.Module.customSections(module, "name");
console.log(sections);
})
</script>
</body>
</html>
得到的自定义区域内容体现为一个ArrayBuffer对象,它在网页调试控制台中有如下的显示。
二、WebAssembly.Module.imports & WebAssembly.Module.exports
WebAssembly.Module还定义了两个名称为imports 和exports的静态方法,我们可以利用它们得到wasm模块导入和导出对象的描述,接下来我们就将它们应用到我们的演示程序中。在index.html页面中,WebAssembly.Module对象创建出来后,我们将它作为参数传入上述两个静态方法中,然后将它们组合成又给对象,并以JSON的形式直接显示在页面里。
<html>
<head></head>
<body>
<pre><code id="code"></code></pre>
<script>
fetch("app.wasm")
.then((response) => response.arrayBuffer())
.then(bytes => {
var module = new WebAssembly.Module(bytes);
var imports = WebAssembly.Module.imports(module);
var exports = WebAssembly.Module.exports(module);
document.getElementById("code").innerText = JSON.stringify({"imports":imports, "exports":exports}, null, 2);
})
</script>
</body>
</html>
针对导入/导出描述的JSON以下的形式承载的页面中,可以看出导入描述中包含了每个导入对象的路径(“{module}.{name}”)和类型(function、table、memory和global)。导出描述包含了每个导出对象的导出名称和类型。
三、WebAssembly.Instance.exports
WebAssembly.Module仅仅是对加载的wasm模块的描述,宿主程序真正消费的是根据它创建的实例,该实例通过WebAssembly.Instance类型表示。WebAssembly.Instance构造函数具有两个参数,分别是提供描述元数据的WebAssembly.Module和指定的导入对象。宿主程序能够使用的仅仅是该实例导出的成员,它们通过WebAssembly.Instance对象的exports属性暴露出来。在如下所示的代码片段中,我们对index.html作了相应的修改来演示WebAssembly.Instance对象的导出列表。
<html>
<head></head>
<body>
<script>
fetch("app.wasm")
.then((response) => response.arrayBuffer())
.then(bytes => {
var module = new WebAssembly.Module(bytes);
var imports = {
"func": ()=> {},
"memory": new WebAssembly.Memory({ initial: 1 }),
"table": new WebAssembly.Table({ initial: 4, element: "externref" }),
"global": new WebAssembly.Global({ value: "i32", mutable:true, initial:0})
};
var instance = new WebAssembly.Instance(module, {imports});
console.log(instance);
})
</script>
</body>
</html>
如代码片段所示,在得到描述wasm模块的WebAssembly.Module对象后,我们创建出对应的导入对象,并将它们作为参数调用构造函数将WebAssembly.Instance对象创建出来,并将其exports属性代表的导出对象输出到调试控制台上。下图展示了导出列表在控制台中的输出,可以看出它们与app.wat程序是一致的。
WebAssembly核心编程[3]: Module 与 Instance的更多相关文章
- python核心编程第二版笔记
python核心编程第二版笔记由网友提供:open168 python核心编程--笔记(很详细,建议收藏) 解释器options:1.1 –d 提供调试输出1.2 –O 生成优化的字节码(生成 ...
- python核心编程--笔记
python核心编程--笔记 的解释器options: 1.1 –d 提供调试输出 1.2 –O 生成优化的字节码(生成.pyo文件) 1.3 –S 不导入site模块以在启动时查找pyt ...
- python核心编程--笔记(不定时跟新)(转)
的解释器options: 1.1 –d 提供调试输出 1.2 –O 生成优化的字节码(生成.pyo文件) 1.3 –S 不导入site模块以在启动时查找python路径 1.4 –v ...
- python核心编程笔记(转)
解释器options: 1.1 –d 提供调试输出 1.2 –O 生成优化的字节码(生成.pyo文件) 1.3 –S 不导入site模块以在启动时查找python路径 1.4 –v 冗 ...
- Python核心编程-描述符
python中,什么描述符.描述符就是实现了"__get__"."__set__"或"__delete__" 方法中至少一个的对象.什么是非 ...
- 学习《Python核心编程》做一下知识点提要,方便复习(一)
学习<Python核心编程>做一下知识点提要,方便复习. 计算机语言的本质是什么? a-z.A-Z.符号.数字等等组合成符合语法的字符串.供编译器.解释器翻译. 字母组合后产生各种变化拿p ...
- pytho核心编程2-1中代码运行问题
书籍是<python核心编程>第三版,学习环境py3.6 2-1 时间戳服务器 附源代码: from socket import * from time import ctime HOST ...
- windows核心编程 DLL技术 【转】
注:本文章转载于网络,源地址为:http://blog.csdn.net/ithzhang/article/details/7051558 本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑 ...
- 《Windows核心编程系列》二十谈谈DLL高级技术
本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑定的技术. 第一种将DLL映射到进程地址空间的方式是直接在源代码中引用DLL中所包含的函数或是变量,DLL在程序运行后由加载程序隐式的载入, ...
- Spark详解(05) - Spark核心编程SparkCore
Spark详解(05) - Spark核心编程SparkCore RDD概述 什么是RDD RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基 ...
随机推荐
- JXUST_NC - ACM工作室20级选拔赛题解
A - RioTian学长的星际航线 并查集板子 #include <bits/stdc++.h> using namespace std; const int maxn = 1010; ...
- jdk1.8(java8)新特性
借鉴之:https://blog.csdn.net/qq_28410283/article/details/80601495 Lambda 表达式: //1.Lambda 表达式,也可称为闭包,它是推 ...
- 十三、docker的四种网络类型
系列导航 一.docker入门(概念) 二.docker的安装和镜像管理 三.docker容器的常用命令 四.容器的网络访问 五.容器端口转发 六.docker数据卷 七.手动制作docker镜像 八 ...
- Linux 文件目录配置及命令总结
前言 在Linux中,一切皆文件,而每一个文件和目录都是从根目录开始的 Linux文件目录的作用 /bin目录:用来存放二进制可执行命令的目录,用户常用的命令都存在该目录下. /sbin目录:用来存放 ...
- GoLang 指针初探
1. 内置类型和引用类型 Go 中内置类型包括数值类型,字符串类型和布尔类型.引用类型包括切片,映射,通道,接口和函数类型.其中,引用类型表示创建的变量包含一个指向底层数据结构的指针和一组管理底层数据 ...
- SpringBoot3集成Zookeeper
标签:Zookeeper3.8 ,Curator5.5: 一.简介 ZooKeeper是一个集中的服务,用于维护配置信息.命名.提供分布式同步.提供组服务.分布式应用程序以某种形式使用所有这些类型的服 ...
- [转帖]Windows自带MD5 SHA1 SHA256命令行工具
https://www.cnblogs.com/huangrt/p/13961399.html 检验工具http://www.zdfans.com/html/4346.html HashMyFiles ...
- [转帖]如何部署windows版本的oswatcher
2017-02-22 没有评论 windows上也有os watcher:OSWFW. 目前支持的windows版本是: Windows XP (x86 & x64)Windows 7 (x8 ...
- [转帖]Kafka 核心技术与实战学习笔记(八)kafka集群参数配置(下)
一.Topic级别参数 Topic的优先级: 如果同时设置Topic级别参数和全局Broker参数,那么Topic级别优先 消息保存方面: retention.ms:规定Topic消息保存时长.默认是 ...
- 关于cockpit的学习
关于cockpit的学习 背景 使用node-exporter 可以监控很多资源使用情况 但是这个需要搭建一套prometheus和grafana的工具 并且每个机器都需要安装一套node-expor ...