Skip to content

WebAssembly

· 2 min

函数#

;; // 定义函数
(func (param i32) (param f32) (local f64)
local.get 0
local.get 1
local.get 2)
// 别名
(func (param $p1 i32) (param $p2 f32) (local $loc f64)
local.get $p1
local.get $p2
local.get $loc)
;; // 导出函数
(module
(func $add (param $lhs i32) (param $rhs i32) (result i32)
local.get $lhs
local.get $rhs
i32.add)
(export "add" (func $add))
)
;; // 函数调用
(module
(func $getAnswer (result i32)
i32.const 42)
(func (export "getAnswerPlus1") (result i32) ;; 函数定义导出的简写形式
call $getAnswer
i32.const 1
i32.add))
;; // 导入
(module
(import "console" "log" (func $log (param i32))) ;; 使用了两级命名空间
(func (export "logIt")
i32.const 13
call $log))

内存#

可以使用 js 创建内存对象,导入 WebAssembly, 也可以在 WebAssembly 模块中创建内存导出。

指令集#

控制指令#

参数指令#

变量指令#

内存指令#

local 指令#

用于操作函数的局部变量。

local.get $index($index 是变量索引或名称)将局部变量的值压入操作数栈顶。

local.set $index 从操作数栈顶弹出一个值,并赋给指定局部变量。

(func (local $x i32)
i32.const 42
local.set $x ;; $x = 42
)

local.tee $index 类似 local.set,但保留栈顶值(赋值后重新压回栈)。

数值指令#

i32#

i32.load offset=X align=Y 从内存加载 i32 值。

;; 栈顶压入地址
i32.const 0x100
;; 执行加载
i32.load offset=8
;; 实际访问地址 = 0x100 + 8 = 0x108

Rust#

数组和对象传递#

// let array = [1,2,3,4,5,6,7,8,9];
pub fn test(array: JsValue) {
let elements: Vec<u32> = array.into_serde().unwrap();
}
#[derive(Serialize, Deserialize)]
pub struct Element {
name: String,
id: String,
parent_id: String,
}
// let js_object = {name: "hello world", id: "99", parent_id: "11"};
pub fn test(js_object: &JsValue) {
let element: Element = js_object.into_serde().unwrap();
}

https://www.coder.work/article/2554080

闭包问题#

https://cloud.tencent.com/developer/ask/sof/765656

https://stackoverflow.com/questions/53214434/how-to-return-a-rust-closure-to-javascript-via-webassembly/53219594#53219594

资料#

Rust 🦀 和 WebAssembly 🕸

wasm-bindgen 指南