1、簡單的C/C++ 編寫
我們可以將C 代碼 編譯成wasm 文件供js 調用,C 文件的寫法和我們普通的C寫法並沒有太大區別,不需要太多的封裝,連main 入口都可以丟棄。例如C實現一個簡單的加法計算
#include <stdio.h>
int add(int a, int b)
{
int sum = a + b;
printf("計算結果 %d\n", sum);
return sum;
}
編寫腳本,編譯C 文件成wasm 文件
rm *.js *.wasm
export EXPORTED_FUNCTIONS="['_add']"
emcc add.c \
-s EXPORTED_FUNCTIONS="${EXPORTED_FUNCTIONS}" \
-o add.js
-o 后綴名是js,指示編譯器只生成wasm 以及js, 不生成默認的html 文件。
EXPORTED_FUNCTIONS ,將函數導出
編寫html 文件調用wasm。
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<script>
Module = {};
Module.onRuntimeInitialized = function() {
console.log("計算結果:" + Module._add(12, 5));
}
</script>
<script src="add.js"></script>
</body>
</html>
Module是一個封裝器對象,實現了C語言方法的導出,調用C 方法只需要Module._方法名即可。
2、數據交互
在實際的使用中,C語言經常使用malloc,free 等內存操作函數,而且一般傳參都會傳指針。這次在js端傳入一個數組,C端完成計算並返回。
修改index.html,添加以下方法
function addBatch()
{
var num = 5;
var inputPtr = Module._malloc(4 * 5);
for(i = 0;i<num;i++)
{
Module.HEAP32[(inputPtr)>>2 + i] = i;
}
var sum = Module._addArry(inputPtr, num);
console.log("數組計算結果:" + sum);
Module._free(inputPtr);
}
JavaScript中的ArrayBuffer無法直接訪問,必須通過某種類型的TypedArray方可對其進行讀寫,這里是將js 的數據寫如一個Module.HEAP32 中,然后再傳入C 中。Module._alloc /Module._free 對應於C 中的malloc/free ,需要在編譯腳本中導出,不然會出現找不到
函數的錯誤。
rm *.js *.wasm
export TOTAL_MEMORY=10485760
export EXPORTED_FUNCTIONS="['_add', '_addArry', '_malloc', '_free']"
emcc add.c \
-s EXPORTED_FUNCTIONS="${EXPORTED_FUNCTIONS}" \
-s TOTAL_MEMORY=${TOTAL_MEMORY} \
-o add.js
echo "編譯完成"
-s TOTAL_MEMORY 這個選項要加上,不然無法分配內存,報alloc memory error 錯誤。
對象 TypedArray 對應C數據類型
Module.HEAP8 Int8Array int8
Module.HEAP16 Int16Array int16
Module.HEAP32 Int32Array int32
Module.HEAPU8 Uint8Array uint8
Module.HEAPU16 Uint16Array uint16
Module.HEAPU32 Uint32Array uint32
Module.HEAPF32 Float32Array float
Module.HEAPF64 Float64Array double
最后啟動一個npm 安裝http-server,啟動服務器,搞定收工!
npm install http-server -g
http-server
參考資料
https://www.cntofu.com/book/150/zh/ch2-c-js/ch2-03-mem-model.md