来自 奥门威尼斯网址 2019-09-21 03:40 的文章
当前位置: 威尼斯国际官方网站 > 奥门威尼斯网址 > 正文

的那些事,关于WebAssembly的详细讲述

webAssembly.Memory

当 WebAssembly 模块被实例化时,它需要一个 memory 对象。你可以创建一个新的WebAssembly.Memory并传递该对象。如果没有创建 memory 对象,在模块实例化的时候将会自动创建,并且传递给实例。图片 1

memoryDescriptor (object)

  • initial
  • maximum 可选

webAssembly.Module

WebAssembly.Module() 构造函数可以用来同步编译给定的 WebAssembly 二进制代码。不过,获取 Module 对象的主要方法是通过异步编译函数,如 WebAssembly.compile(),或者是通过 IndexedDB 读取 Module 对象.

var myInstance = new WebAssembly.Instance(module, importObject);

module: 需要被实例化的webAssembly module importObject: 需要导入的变量

webAssembly.instantiate图片 2

Rust编译为webAssembly

1.安装Rustup

Rustup是一个命令行应用,能够下载并在不同版本的Rust工具链中进行切换

brew install cargo

curl https://sh.rustup.rs -sSf | sh

source $HOME/.cargo/env 

source  ~/.bash_profile

rustup target add wasm32-unknown-unknown --toolchain nightly 

cargo install --git https://github.com/alexcrichton/wasm-gc 

//减小wasm的size

cargo可以将整个工程编译为wasm,首先使用cargo创建工程:

cargo new project

下一步,把下面的代码加到 Cargo.toml 中

[lib]

path = "src/lib.rs"

crate-type = ["cdylib"]

2.demo:

编译:

cargo +nightly build --target wasm32-unknown-unknown --release

图片 3

编译出来的wasm大小为82Kb,使用wasm-gc压缩 small-wasm_astar.wasm 的大小为 67Kb

wasm-gc wasm_astar.wasm small-wasm_astar.wasm

图片 4

未来功能

  • 直接操作DOM
  • 支持多数据(SIMD):SIMD的使用可以获取大的数据结构,例如不同数目的向量,并且同时将相同的指令应用于不同的部分。这样,它可以大大加快各种复杂计算的游戏或VR的运行速度。
  • ES6模块集成:浏览器目前正在添加对使用script标签加载JavaScript模块的支持。 添加此功能后,即使URL指向WebAssembly模块,

    1 赞 2 收藏 评论

图片 5

更直观的例子

上面的例子中,编译后即可直接运行。但是生成的代码体积较大,不容易看懂具体做了什么。因此下面提供一个更直观的例子。

math.c

int add (int x, int y) {

  return x + y;

}

int square (int x) {

  return x * x;

}

编译:

emcc math.c -Os -s WASM=1 -s SIDE_MODULE=1 -o math.wasm

-s SIDE_MODULE=1 直接由C生成wasm文件

目前只有一种方式能调用 wasm 里的提供接口,那就是:用 javascript !

webAssembly.compile

WebAssembly.compile() 方法编译WebAssembly二进制代码到一个WebAssembly.Module 对象。图片 6

webAssembly.Table

var myTable = new WebAssembly.Table(tableDescriptor);

tableDescriptor (object)

element,当前只支持一个值。 ‘anyfunc’ initial, WebAssembly Table的初始元素数 maximum(可选), 允许的最大元素数

webAssembly使用

WebAssembly 与其他的汇编语言不一样,它不依赖于具体的物理机器。可以抽象地理解成它是概念机器的机器语言,而不是实际的物理机器的机器语言。浏览器把 WebAssembly 下载下来后,可以迅速地将其转换成机器汇编代码。

图片 7

快速体验webAssembly

图片 8

使用C/C++

hello.c

图片 9

编译:

图片 10

  • -s WASM=1 — 指定我们想要的wasm输出形式。如果我们不指定这个选项,Emscripten默认将只会生成asm.js。
  • -o hello.html — 指定这个选项将会生成HTML页面来运行我们的代码,并且会生成wasm模块以及编译和实例化wasim模块所需要的“胶水”js代码,这样我们就可以直接在web环境中使用了。

编译后图片 11

 

  1. 二进制的wasm模块代码 (hello.wasm)
  2. 一个包含了用来在原生C函数和JavaScript/wasm之间转换的胶水代码的JavaScript文件 (hello.js)
  3. 一个用来加载,编译,实例化你的wasm代码并且将它输出在浏览器显示上的一个HTML文件 (hello.html)

调用C++中的方法

hello.c

图片 12

如果想调用hello2.c中的myFunction方法,则需要将ccall方法从Moudule导出。使用下面的编译命令:图片 13

  • htmltemplate/shellminimal.html 指定为HTML模板。
  • -s ‘EXTRAEXPORTEDRUNTIME_METHODS=[“ccall”]’ 从Module中导出 ccall

将 ccall 方法导出之后,就可以使用 Module.ccall来调用C++中的函数了。图片 14

编写加载函数(loader)

function loadWebAssembly (path) {

  return fetch(path)                   // 加载文件        

    .then(res => res.arrayBuffer())    // 转成 ArrayBuffer

    .then(WebAssembly.instantiate)     // 编译 + 实例化

    .then(mod => mod.instance)         // 提取生成都模块

}

完成了上边的操作,就可以直接使用 loadWebAssembly 这个方法加载 wasm 文件了,它相当于是一个 wasm-loader ;返回值是一个 Promise.

loadWebAssembly('path/to/math.wasm')

  .then(instance => {

    const { add, square } = instance.exports

    // ...

})

更完善的loader

function loadWebAssembly(filename, imports = {}) {

return fetch(filename)

    .then(response => response.arrayBuffer())

    .then(buffer => WebAssembly.compile(buffer)) 

    //WebAssembly.compile 可以用来编译 wasm 的二进制源码,

    //它接受 BufferSource 格式的参数,返回一个 Promise。

    .then(module => {           

        imports.env = imports.env || {};

        // 开辟内存空间 && 创建变量映射表

        Object.assign(imports.env, {

            memoryBase: 0,

            tableBase: 0,

            memory: new WebAssembly.Memory({ initial: 256, maximum: 256 }),

            table: new WebAssembly.Table({ initial: 0, maximum: 0, 

                    element: 'anyfunc' })

        })

        // 创建 WebAssembly 实例

        return new WebAssembly.instantiate(module, imports)

    })

}

ArrayBuffer 做了两件事情,一件是做 WebAssembly 的内存,另外一件是做 JavaScript 的对象。

它使 JS 和 WebAssembly 之间传递内容更方便。 使内存管理更安全。

这个 loadWebAssembly 函数还接受第二个参数,表示要传递给 wasm 的变量,在初始化 WebAssembly 实例的时候,可以把一些接口传递给 wasm 代码。

webAssembly.Table图片 15

tableDescriptor (object)

  • element,当前只支持一个值。 ‘anyfunc’
  • initial, WebAssembly Table的初始元素数
  • maximum(可选), 允许的最大元素数

webAssembly.instantiate

Promise WebAssembly.instantiate(module, importObject);

webAssembly.validate

webAssembly.validate() 方法验证给定的二进制代码的 typed array 是否是合法的wasm module.返回布尔值。图片 16

使用

图片 17

webAssembly.Module

WebAssembly.Module() 构造函数可以用来同步编译给定的 WebAssembly 二进制代码。不过,获取 Module 对象的主要方法是通过异步编译函数,如 WebAssembly.compile(),或者是通过 IndexedDB 读取 Module 对象.图片 18

参数: 一个包含你想编译的wasm模块二进制代码的 typed array(类型数组) or ArrayBuffer(数组缓冲区).

重要提示:由于大型模块的编译可能很消耗资源,开发人员只有在绝对需要同步编译时,才使用 Module() 构造函数;其他情况下,应该使用异步 WebAssembly.compile() 方法。

未来功能

直接操作DOM 支持多数据(SIMD):SIMD的使用可以获取大的数据结构,例如不同数目的向量,并且同时将相同的指令应用于不同的部分。这样,它可以大大加快各种复杂计算的游戏或VR的运行速度。 ES6模块集成:浏览器目前正在添加对使用script标签加载JavaScript模块的支持。 添加此功能后,即使URL指向WebAssembly模块, <

asm.js

asm.js 是 javascript 的子集,是一种语法。用了很多底层语法来标注数据类型,目的是提高 javascript 的运行效率,本身就是作为 C/C++ 编译的目标设计的(不是给人写的)。 WebAssembly 借鉴了这个思路,做的更彻底一些,直接跳过 javascript ,设计了一套新的平台指令。

目前只有 asm.js 才能转成 wasm,普通 javascript 是不行的。虽然 Emscripten 能生成 asm.js 和 wasm ,但是却不能把 asm.js 转成 wasm 。想要把 asm.js 编译成 WebAssembly,就要用到他们官方提供的 Binaryen 和 WABT (WebAssembly Binary Toolkit) 工具。图片 19

asm.js

asm.js 是 javascript 的子集,是一种语法。用了很多底层语法来标注数据类型,目的是提高 javascript 的运行效率,本身就是作为 C/C++ 编译的目标设计的(不是给人写的)。 WebAssembly 借鉴了这个思路,做的更彻底一些,直接跳过 javascript ,设计了一套新的平台指令。

目前只有 asm.js 才能转成 wasm,普通 javascript 是不行的。虽然 Emscripten 能生成 asm.js 和 wasm ,但是却不能把 asm.js 转成 wasm 。想要把 asm.js 编译成 WebAssembly,就要用到他们官方提供的 Binaryen 和 WABT (WebAssembly Binary Toolkit) 工具。

           Binaryen                WABT

math.js   -------->   math.wast   ------->   math.wasm

本文由威尼斯国际官方网站发布于奥门威尼斯网址,转载请注明出处:的那些事,关于WebAssembly的详细讲述

关键词: