在這里就不科普webassemly的作用以及好處了,請自行百度。
那么,怎么通過js的方式在瀏覽器中運行c程序呢,其中原理如下:
可能另一張圖會更詳細:
1.安裝emscripten
說明文檔地址:https://emscripten.org/docs/getting_started/downloads.html
以下步驟為macOs下命令:
step1:克隆項目------------git clone https://github.com/emscripten-core/emsdk.git
step2:進入項目目錄--------cd emsdk
step3:安裝最新emsdk工具---./emsdk install latest
step4:激活---------------./emsdk activate latest
step5:執行批處理添加環境變量source ./emsdk_env.sh
已經安裝好了,看一下版本:
2.寫一個c文件(test.c)並轉換.wasm
#include <emscripten/emscripten.h> int EMSCRIPTEN_KEEPALIVE add(int a, int b) { return a + b; } int EMSCRIPTEN_KEEPALIVE fibonacci(int n) { if (n <= 1) { return n; } else { return fibonacci(n - 1) + fibonacci(n - 2); } }
注意,紅字必須,這是相比常規c文件不同的地方。
轉換命令:
emcc test.c -Os -s WASM=1 -s SIDE_MODULE=1 -o test.wasm
然后你就在相同目錄下得到了一個test.wasm文件。
3.通過js引入.wasm並執行其中函數
這里我封裝了一個引入.wasm文件的工具函數,代碼如下:
const importObj = { global: {}, env: { 'memory': new WebAssembly.Memory({initial: 256, maximum: 256}), '__memory_base': 0, 'tableBase': 0, 'table': new WebAssembly.Table({initial: 10, element: 'anyfunc'}), abort:alert } }; export async function addModule(url,callback){ fetch(url).then(response => response.arrayBuffer() ).then(bytes => WebAssembly.instantiate(bytes,importObj)).then(results => { var instance = results.instance; var module = instance.exports; callback(module); }); }
index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>WebAssemblyLearning</title> </head> <body> </body> <script type="module"> import {addModule} from './utils/wasm.js'; var num = 42; function getDuring(func,type){ const start = Date.now(); func(num); console.log(type +'執行斐波那契數列消耗時間:' +(Date.now() - start) + 'ms\n'); }; addModule('./add.wasm',function(module){ getDuring(module._fibonacci,'C程序'); }); function fibonacci(n) { if (n <= 1) { return n; } else { return fibonacci(n - 1) + fibonacci(n - 2); }; }; console.error('遞歸次數:'+ num); getDuring(fibonacci,'JavaScript') </script> </html>
我們看到,上面通過兩種不同的方式執行了一個遞歸次數為42的斐波那契數列求和函數,對比一下兩者的性能:
所以對於追求性能的web程序來說,webassemly將是一個很好的選擇。