WebAssembly入门笔记[3]:如何用Table传递引用实现引用传递?

摘要:在《WebAssembly入门笔记[2]》中,我们介绍了如何利用Memory在作为宿主的JavaScript应用和wasm模块之间传递数据,但是Memory面向单纯二进制字节的读写在使用起来还是不太方便,此时我们会更多地用到另一个重要的对象
在《WebAssembly入门笔记[2]》中,我们介绍了如何利用Memory在作为宿主的JavaScript应用和wasm模块之间传递数据,但是Memory面向单纯二进制字节的读写在使用起来还是不太方便,此时我们会更多地用到另一个重要的对象Table。Table利用用来存储一组指定类型的对象,说得准确一点是对象的引用,所以可以读取出来直接消费。 一、利用Table存储wasm函数引用 二、执行call_indirect执行函数 三、利用Table存储JavaScript函数引用 一、利用Table存储wasm函数引用就目前的版本来说,Table只支持funcref和externref两种引用类型,前者表示wasm原生函数,后者则用来存储宿主程序提供的任何JavaScript对象,所以如果存储JavaScript函数,Table元素的类型必需指定为externref。下面的实例演示了这样的场景:wasm模块将自身定义的函数存储在导出的Table中供宿主程序使用。 如下所示的采用WebAssembly Text(WAT)格式定义的app.wat文件的定义。我们定义了用来执行加、减、乘、除运算的四个函数,并将它们存储在导出的Table中。由于存储的是wasm函数,所以Table定义语句(table (export "table") funcref (elem $add $sub $mul $div))将元素类型设置为funcref。我们利用elem语句将四个函数的引用填充到Table中。(源代码) (module (func $add (param $op1 i32) (param $op2 i32) (result i32) (local.get $op1) (local.get $op2) (i32.add) ) (func $sub (param $op1 i32) (param $op2 i32) (result i32) (local.get $op1) (local.get $op2) (i32.sub) ) (func $mul (param $op1 i32) (param $op2 i32) (result i32) (local.get $op1) (local.get $op2) (i32.mul) ) (func $div (param $op1 i32) (param $op2 i32) (result i32) (local.get $op1) (local.get $op2) (i32.div_u) ) (table (export "table") funcref (elem $add $sub $mul $div)) )上面的定义主要是为了解释wasm基于“堆栈”的参数传递方式,代码相对繁琐。如果切换如下所示的“嵌套模式”,就会简洁很多。(源代码) (module (func $add (param $op1 i32) (param $op2 i32) (result i32) (i32.add (local.get $op1) (local.get $op2)) ) (func $sub (param $op1 i32) (param $op2 i32) (result i32) (i32.sub (local.get $op1) (local.get $op2)) ) (func $mul (param $op1 i32) (param $op2 i32) (result i32) (i32.mul (local.get $op1) (local.get $op2)) ) (func $div (param $op1 i32) (param $op2 i32) (result i32) (i32.div_u (local.get $op1) (local.get $op2)) ) (table (export "table") funcref (elem $add $sub $mul $div)) )在承载宿主应用的index.html中,在得到导出的Table对象之后,我们将存储(0-3)的位置作为参数调用其get方法得到对应的wasm函数。我们传入相同的参数(2,1)调用这四个函数。
阅读全文