WebAssembly使用入门介绍

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为本文内容做出的大力贡献!😄😄

关于chenzujie

非著名码农一枚,认真工作,快乐生活
此条目发表在Nodejs, 前端分类目录。将固定链接加入收藏夹。

WebAssembly使用入门介绍》有一条回应

发表评论

邮箱地址不会被公开。 必填项已用*标注