WebAssembly入门

  目录

WebAssembly简单实例

WebAssembly入门

本文章代码运行环境window11

什么是 WebAssembly?

WebAssembly(简称 WASM)是一种可以在现代 Web 浏览器中运行的二进制格式。它是一种与平台无关的低级语言,旨在提供接近原生性能的执行速度,主要用于提升 Web 应用的性能,支持多种编程语言(如 C、C++、Rust 等)编译成 WebAssembly 代码,运行在浏览器中。

WebAssembly 的特点

  • 高性能:接近原生速度的执行性能,适合计算密集型任务。
  • 多语言支持:支持 C、C++、Rust、Go 等语言编译为 WASM。
  • 跨平台:同一份代码可以在不同的操作系统和浏览器中运行。
  • 安全性:通过浏览器沙箱环境隔离,增强了执行代码的安全性。
  • 模块化:支持模块化加载,便于代码拆分和复用。

WebAssembly 的应用场景

  • 性能要求高的应用:如游戏、图像处理、音视频编码、3D 渲染等。
  • 现有代码复用:将已有的 C、C++ 库移植到 Web 环境。
  • 多语言支持:结合 JavaScript 进行复杂应用开发。

WebAssembly实践

环境准备

安装Emscripten工具链(C/C++ 编译为 WebAssembly 的工具)

1
2
3
4
5
6
# 安装 Emscripten
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
emsdk install latest
emsdk activate latest
emsdk_env.bat

之后运行emcc -v可以看到版本信息。

编写第一个 WebAssembly 程序

编写 C 语言代码

创建一个 hello.c 文件,代码如下:

1
2
3
4
5
6
#include <stdio.h>

int main() {
printf("Hello, WebAssembly!\n");
return 0;
}

编译为 WebAssembly

使用 Emscripten 工具链将 C 代码编译为 WASM 文件

1
emcc hello.c -o hello.html

该命令会生成以下文件:

  • hello.html:用于测试 WebAssembly 的 HTML 页面。
  • hello.js:WebAssembly 模块的加载器。
  • hello.wasm:编译后的 WebAssembly 文件。

运行WebAssembly

可以使用http-server启动服务

使用WebAssembly与JavaScript交互

创建一个C语言文件

创建一个 hello.c 文件,代码如下:

1
2
3
4
5
6
#include <emscripten/emscripten.h>

EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
return a + b;
}

编译并生成WebAssembly

1
emcc hello.c -o hello.js -sEXPORTED_FUNCTIONS="[\"_add\"]" -sEXPORTED_RUNTIME_METHODS="[\"ccall\", \"cwrap\"]"

在HTML文件中加载并调用WebAssembly

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<title>WebAssembly Demo</title>
</head>
<body>
<h1>WebAssembly 加法示例</h1>
<script src="hello.js"></script>
<script>
Module.onRuntimeInitialized = () => {
const add = Module.cwrap('add', 'number', ['number', 'number']);
console.log('1 + 2 =', add(1, 2));
};
</script>
</body>
</html>

JavaScript调用C++

编写C++代码

创建math.cpp文件,代码如下:

1
2
3
4
5
6
7
8
#include <emscripten/emscripten.h>

extern "C" {
EMSCRIPTEN_KEEPALIVE
int multiply(int a, int b) {
return a * b;
}
}

编译为WebAssembly

1
emcc math.cpp -o math.js -sEXPORTED_FUNCTIONS="[\"_multiply\"]" -sEXPORTED_RUNTIME_METHODS="[\"cwrap\"]"

调用C++函数

html文件中添加以下代码

1
2
3
4
5
6
7
<script src="math.js"></script>
<script>
Module.onRuntimeInitialized = () => {
const multiply = Module.cwrap('multiply', 'number', ['number', 'number']);
console.log('3 * 4 =', multiply(3, 4));
};
</script>

C++调用JavaScript

编写C++代码

创建math.cpp文件,代码如下:

1
2
3
4
5
6
7
8
9
#include <emscripten/emscripten.h>
#include <emscripten/bind.h>

extern "C" {
EMSCRIPTEN_KEEPALIVE
void call_js() {
emscripten_run_script("console.log('Hello from C++!')");
}
}

编译为WebAssembly

1
emcc math.cpp -o math.js -sEXPORTED_FUNCTIONS="[\"_call_js\"]" -sEXPORTED_RUNTIME_METHODS="[\"ccall\"]"

在JavaScript中执行

1
2
3
4
5
6
<script src="math.js"></script>
<script>
Module.onRuntimeInitialized = () => {
Module.ccall('call_js');
};
</script>

WebAssembly生态工具

  • Emscripten:C/C++ 到 WebAssembly 的编译工具。
  • wasm-pack:用于将 Rust 代码编译为 WebAssembly。
  • AssemblyScript:使用 TypeScript 编写 WebAssembly。
  • Binaryen:WebAssembly 优化和工具链。

总结

以上简单的介绍了WebAssembly,还有几个小例子