WebAssembly是什么?
WebAssembly(通常缩写为wasm)是一种基于堆栈的虚拟机的二进制指令格式。它被设计为一种低级、可移植的字节码,可在Web浏览器和其他环境中执行,它设计的目的不是为了手写代码而是为诸如 C、C++和 Rust 等低级源语言提供一个高效的编译目标。
WebAssembly是一种新型的代码,可与HTML、CSS和JavaScript一起用于Web或者Nodejs开发。
WebAssembly比JavaScript具有许多优势。它更快,能够处理更多的数据,也更容易在不同的平台上实现相同的功能。
使用WebAssembly方式
WebAssembly 当前,有四个主要的着手点:
- 使用 Emscripten 移植一个 C/C++应用程序。
- 直接在汇编层,编写或生成 WebAssembly 代码。
- 编写 Rust 程序,将 WebAssembly 作为它的输出。
- 使用AssemblyScript,它类似于 TypeScript 并且可编译成二进制 WebAssmebly 代码
使用Emscripten移植一个C/C++应用程序
安装Emscripten
安装EMScripten需要以下步骤:
- 安装依赖
EMScripten需要依赖于Python和Node.js,因此需要先安装它们。建议安装Python2.7.x版本和Node.js8.x版本。
- 下载和安装EMScripten
可以通过git从EMScripten的官方仓库中获取最新的代码库:
git clone https://github.com/emscripten-core/emsdk.git
进入emsdk目录,执行以下命令来安装EMScripten:
./emsdk install latest
安装完成后,执行以下命令来激活EMScripten:
./emsdk activate latest
- 配置环境变量
安装完成后,需要将EMScripten的工具路径添加到系统的PATH环境变量中,以便可以在命令行中正常使用EMScripten。
在Linux或MacOS系统中,可以在用户主目录下的.bashrc或.zshrc文件中添加以下行:
source ~/emsdk/emsdk_env.sh
在Windows系统中,可以在系统环境变量或用户环境变量中添加EMS_HOME变量,将其值设置为EMS的安装目录,例如C:emsdk,并将%EMS_HOME
使用Emscripten将c/c++程序编译成wasm
比如我们有如下c代码 testWebAssembly.c
#include <stdio.h>
int output()
{
return 1;
}
int add(int a, int b)
{
return a + b;
}
emcc testWebAssembly.c -Os -s WASM=1 -s SIDE_MODULE=1 -o testWebAssembly.wasm
上面的编译选项-s WASM=1是告诉编译器将代码编译成一个 WebAssembly 模块(即侧向模块),而不是一个完整的可执行程序。这意味着该程序不包含 main 函数,也不包含任何与操作系统或文件系统相关的代码。这使得该程序可以被其他程序通过 WebAssembly API 调用,并且可以在各种不同的环境中运行,例如浏览器、Node.js 等。
我一开始编译确实-s SIDE_MODULE=1,导致编译出来的testWebAssembly.wasm在实际使用的时候一直报错如下,加了该选项之后就正常
WebAssembly.Instance(): Import #0 module="wasi_snapshot_preview1" error: module is not an object or function
-s WASM=1是 emsdk / emscripten 中的一个编译选项,它告诉 emscripten 编译器将输出编译为 WebAssembly 格式。具体来说,它启用了 Emscripten 的 WebAssembly 后端,该后端将 C/C++代码编译为 WebAssembly 模块。
在使用 Emscripten 编译 C/C++代码时,如果希望将其编译为 WebAssembly 格式,必须使用 -s WASM=1选项。如果您没有使用该选项,编译器将默认为 asm.js 格式进行编译。
WebAssembly 是一种新型的低级字节码格式,可以在浏览器中运行,能够以可移植的方式在不同的平台上执行代码。相比于 asm.js,WebAssembly 具有更快的解析速度和更小的体积,这使得它成为用于在浏览器中运行原生代码的最佳选择之一。
通过以上方式我们最终得到一个testWebAssembly.wasm
在Nodejs中使用WebAssembly
const fs = require('fs');
const wasmCode = fs.readFileSync('./testWebAssembly.wasm');
// 编译WebAssembly二进制代码
const wasmModule = new WebAssembly.Module(toUint8Array(wasmCode));
// 实例化WebAssembly模块
const wasmInstance = new WebAssembly.Instance(wasmModule, {});
const lib = wasmInstance.exports;
// `Wasm` does **not** understand node buffers, but thankfully a node buffer
// is easy to convert to a native Uint8Array.
function toUint8Array(buf) {
const u = new Uint8Array(buf.length);
for (let i = 0; i < buf.length; ++i) {
u[i] = buf[i];
}
return u;
}
console.log(lib.add(5, 5));
console.log(lib.output());
最终我们就能成功在nodejs环境里直接调用c/c++代码的方法,使用方式比较简单,直接参看注释。
结语
WebAssembly是一种强大的技术,可以在JavaScript中提供更高效的计算和运行。如果您正在开发需要高性能计算、处理多媒体数据、运行游戏和图形应用程序等应用程序,则可以考虑使用WebAssembly。
但对于一些用户交互界面或者需要频繁和JavaScript做交互的内容则不是WebAssembly的合适使用场景。
最后感谢ChatGPT为本文内容做出的大力贡献!😄😄
en uygun takipçi satın al