WebAssembly - 模組



我們已經瞭解瞭如何從 c/c++ 程式碼中獲取 .wasm 檔案。在本章中,我們將把 wasm 轉換為 WebAssembly 模組,並在瀏覽器中執行它。

讓我們使用如下所示的 C++ 階乘程式碼 -

int fact(int n) {
   if ((n==0)||(n==1))
      return 1;
   else
      return n*fact(n-1);
}

開啟 Wasm Explorer,它位於 https://mbebenita.github.io/WasmExplorer/ 如下所示 -

C++ Factorial Function

第一列包含 C++ 階乘函式,第二列包含 WebAssembly 文字格式,最後一列包含 x86 彙編程式碼。

WebAssembly 文字格式 -

(module
   (table 0 anyfunc)
   (memory $0 1)
   (export "memory" (memory $0))
   (export "_Z4facti" (func $_Z4facti))
   (func $_Z4facti (; 0 ;) (param $0 i32) (result i32)
      (local $1 i32)
      (set_local $1
         (i32.const 1)
      )
      (block $label$0
         (br_if $label$0
            (i32.eq
               (i32.or
                  (get_local $0)
                  (i32.const 1)
               )
               (i32.const 1)
            )
         )
         (set_local $1
            (i32.const 1)
         )
         (loop $label$1
            (set_local $1
               (i32.mul
                  (get_local $0)
                  (get_local $1)
               )
            )
            (br_if $label$1
               (i32.ne
                  (i32.or
                     (tee_local $0
                        (i32.add
                           (get_local $0)
                           (i32.const -1)
                        )
                     )
                     (i32.const 1)
                  )
                  (i32.const 1)
               )
            )
         )
      )
      (get_local $1)
   )
)

C++ 函式 fact 已在 WebAssembly 文字格式中匯出為“_Z4facti”。

單擊下載按鈕下載 wasm 程式碼,並將檔案儲存為 factorial.wasm。

Factorial WASM

現在,要將 .wasm 程式碼轉換為模組,我們需要執行以下操作 -

步驟 1

使用 ArrayBuffer. 將 .wasm 轉換為陣列緩衝區。ArrayBuffer 物件將返回一個固定長度的二進位制資料緩衝區。

步驟 2

來自 ArrayBuffer 的位元組必須使用 WebAssembly.compile(buffer) 函式編譯成模組。

WebAssembly.compile() 函式編譯並從給定的位元組返回一個 WebAssembly.Module。

這是步驟 1 和 2 中討論的 Javascript 程式碼。

<script type="text/javascript">
   let factorial;
   fetch("factorial.wasm")
      .then(bytes => bytes.arrayBuffer())
      .then(mod => WebAssembly.compile(mod))
      .then(module => {return new WebAssembly.Instance(module) })
      .then(instance => {
      
      factorial = instance.exports._Z4facti;
      console.log('Test the output in Brower Console by using factorial(n)');
   });
</script>

程式碼說明

  • Javascript 瀏覽器 API fetch 用於獲取 factorial.wasm 的內容。

  • 使用 arrayBuffer() 將內容轉換為位元組。

  • 透過呼叫 WebAssembly.compile(mod) 從位元組建立模組。

  • 使用 new 建立模組的例項

    WebAssembly.Instance(module)

  • 階乘函式匯出 _Z4facti 透過使用 WebAssembly.Module.exports() 分配給變數 factorial。

示例

這是 module.html 以及 javascript 程式碼 -

module.html

<!doctype html>
<html>
   <head>
      <meta charset="utf-8">
      <title>WebAssembly Module</title>
   </head>
   <body>
      <script>
      let factorial;
      fetch("factorial.wasm")
      .then(bytes => bytes.arrayBuffer())
      .then(mod => WebAssembly.compile(mod))
      .then(module => {return new WebAssembly.Instance(module) })
      .then(instance => {
         factorial = instance.exports._Z4facti;
         console.log('Test the output in Browser Console by using factorial(n)');
      });
      </script>
   </body>
</html>

輸出

在瀏覽器中執行 module.html 以檢視輸出 -

Execute Module Html
廣告