一、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)
})
}