一、C/C++編譯成.wasm
0.背景
準備好本地編譯環境Emscripten,使用emcc命令編譯的.wasm文件在js裏面調用時報這個錯誤:
CompileError: Wasm decoding failedResult = expected magic word 00 61 73 6d, found 42 43 c0 ……
沒找到處理辦法,但是找到了一種更簡單的方法–使用WebAssembly Studio在線編譯。
1、如果只是需要一個.wasm文件,創建Empty C Project
2、main.js和main.html也可以刪除
3、在main.c中編寫c代碼,注意每一個函數上面需要加WASM_EXPORT
4、可以右鍵edit更改輸入、輸出文件名稱,但是注意build.ts文件輸入、輸出文件需要同步
5、最後注意保存文件!再build就編譯生成了.wasm文件
二、javascript加載.wasm文件,調用接口
1、右鍵剛剛生成的.wasm文件download下載
2、測試代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Compile C to WebAssembly</h1>
<p>The test result can be found in console.</p>
<script>
function loadWebAssembly(path) {
return fetch(path) // 加載文件
.then(res => res.arrayBuffer()) // 轉成 ArrayBuffer
.then(WebAssembly.instantiate) // 編譯 + 實例化
.then(mod => mod.instance) // 提取生成都模塊
}
loadWebAssembly('./math.wasm')
.then(instance => {
const add = instance.exports.add;
const sub = instance.exports.sub;
const mul = instance.exports.mul;
const dev = instance.exports.dev;
console.log('1+1 =', add(1, 1));
console.log('1-1 =', sub(1, 1));
console.log('1×6 =', mul(1, 6));
console.log('9÷3 =', dev(9, 3));
});
</script>
</body>
</html>
3、運行結果
4、如果失敗,將第2步的loadWebAssembly
換成這個
/**
* 如果你直接使用上邊那個 loadWebAssembly 函數,有可能會執行失敗,因爲在 wasm 文件裏,可能還會引入一些環境變量,
* 在實例化的同時還需要初始化內存空間和變量映射表,也就是 WebAssembly.Memory 和 WebAssembly.Table。
* @param {String} path wasm 文件路徑
* @param {Object} imports 傳遞到 wasm 代碼中的變量
* @returns {Promise<WebAssembly.Instance>}
*/
function loadWebAssembly(path, imports = {}) {
return fetch(path)
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer))
.then(module => {
imports.env = imports.env || {};
// 開闢內存空間
imports.env.memoryBase = imports.env.memoryBase || 0;
if (!imports.env.memory) {
imports.env.memory = new WebAssembly.Memory({initial: 256})
}
// 創建變量映射表
imports.env.tableBase = imports.env.tableBase || 0;
if (!imports.env.table) {
// 在 MVP 版本中 element 只能是 "anyfunc"
imports.env.table = new WebAssembly.Table({initial: 0, element: 'anyfunc'})
}
// 創建 WebAssembly 實例
return new WebAssembly.Instance(module, imports)
})
}