如何在 Rust 程序中運行 WASM
這篇文章將探索如何在 Rust 應用程序中嵌入 Web Assembly 代碼。我們依賴於 wasmtime,wasmtime 是 WebAssembly 的一個獨立運行時。
創建項目
讓我們從創建一個新的 Rust 項目開始:
$ cargo new rustwasm
$ cd rustwasm
接下來,讓我們安裝幾個 crate:
$ cargo add anyhow
$ cargo add wasmtime
我們在 main.rs 文件中寫入如下代碼:
use anyhow::Result;
use wasmtime::*;
fn main() -> Result<()> {
println!("Compiling module...");
let engine = Engine::default();
let module = Module::from_file(&engine, "hello.wat")?; //(1)
println!("Initializing...");
let mut store = Store::new(
&engine,
()
); //(2)
println!("Creating callback...");
let hello_func = Func::wrap(&mut store, |_caller: Caller<'_, ()>| {
println!("Calling back...");
}); //(3)
println!("Instantiating module...");
let imports = [hello_func.into()];
let instance = Instance::new(&mut store, &module, &imports)?;
println!("Extracting export...");
let run = instance.get_typed_func::<(), ()>(&mut store, "run")?; //(4)
println!("Calling export...");
run.call(&mut store, ())?; //(5)
println!("Done.");
Ok(())
}
第一步:
我們從磁盤加載一個模塊開始。我們正在裝載 hello.wat,默認情況下,將 Web Assembly 代碼發佈成二進制形式。然而,爲了我們的目的,我們依賴於文本表示 (wat)。
第二步:
當運行 wasm 代碼時我們還希望在 host 和 wasm 代碼之間共享一些狀態。通過 Store,我們可以共享這個上下文。在我們的例子中,我們現在不需要共享任何狀態。因此,我們指定一個 Unit 類型作爲 Store::new 的第二個參數。
第三步:
在本文中,我們想讓一個 Rust 函數在 wasm 代碼中可用,然後調用。我們用 Func::wrap 包裝一個 Rust 閉包。這個函數不接受任何參數,而且也不返回任何東西;它只是在調用時打印出 “Calling back”。
第四步:
Wasm 代碼默認情況下沒有主函數,我們把它當做 lib。在我們的例子中,我們期望出現一個 run 函數,我們將使用它作爲我們的入口點。
在調用函數之前,首先需要檢索它。我們還使用 get_typed_func 來指定它的類型簽名。如果我們在二進制文件中找到它,就可以調用它。
第五步:
現在我們找到了函數,讓我們調用它。
Web Assembly 代碼
Rust 程序就緒後,讓我們來看看我們想要加載的 wasm 代碼。在項目根目錄下新建一個 hello.wat 文件:
(module
(func $hello (import "" "hello"))
(func (export "run") (call $hello))
)
wasm 文本格式使用 lisp 語言的 s 表達式。s 表達式是一種非常古老且非常簡單的表示樹的文本格式,因此我們可以將模塊視爲描述模塊結構及其代碼的節點樹。
與編程語言的抽象語法樹不同,WebAssembly 的樹非常扁平,主要由指令列表組成。
這個小程序執行三個任務:
-
它從宿主環境中導入一個名爲 hello 的函數,並將其綁定到本地名稱 $hello。
-
它定義了一個 run 函數,並導出該函數。
-
在 run 函數中,它調用導入的 $hello 函數。
如前所述,.wat(與二進制表示相同) 不是我們通常手寫的東西,而是由工具生成的。
運行
所有組件就緒後,讓我們運行它:
Compiling module...
Initializing...
Creating callback...
Instantiating module...
Extracting export...
Calling export...
Calling back...
Done.
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/qmmJi1Gwz7nZPE47tNnNaQ