---
title: "Emscripten-C++到WebAssembly编译机制"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/05-游戏图形与运行时/WebGL/Emscripten-C++到WebAssembly编译机制.md"
content_hash: 10b1130bf77450a7b65cb7ce355af3d6fb8139f9ec95182f0480d9014af1e557
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# Emscripten-C++到WebAssembly编译机制
## 1. 它是什么

Emscripten 是基于 LLVM 的 **C/C++→WebAssembly** 交叉编译器。
常用入口命令：

* `emcc`  – C 源文件 → WebAssembly
* `em++`  – C++ 源文件 → WebAssembly

---

## 2. 产物长什么样

一次编译通常会生成两份文件：

1. `xxx.wasm` — 二进制指令，真正运行在浏览器 / Node 的模块
2. `xxx.js`  — 运行时与胶水代码，负责加载 WASM、补充系统调用、导出接口

用 `-o out.js` 就会同时写出 `out.wasm`。

---

## 3. 运行时的三种组织方式

| 模式               | 触发方式                               | 用途                                       |
| ---------------- | ---------------------------------- | ---------------------------------------- |
| **单 JS 文件（默认）**  | 不额外设置                              | 最易上手；`out.js` 自动拉取 `out.wasm`            |
| **模块化输出**        | `-sMODULARIZE=1 -sEXPORT_ES6=1`    | 把运行时包装成 ES6 Module / UMD，便于与打包工具集成       |
| **纯 Wasm “独立式”** | `-sSTANDALONE_WASM`（曾用 `-sWASM=2`） | 让 `.wasm` 拥有完整入口表，只需极简 JS 引导即可；适合非 JS 宿主 |

---

## 4. 双向调用：让 C 和 JS 互相干活

* **JS → C**
  * `cwrap` / `ccall` 在运行时直接调用导出的 C 函数。
* **C → JS**
  * 把 JS 函数挂到 `Module` 或通过 `EM_JS`/`emscripten_run_script` 暴露。
  * **怎样让符号“被看见”**

  * 编译时列入 `-sEXPORTED_FUNCTIONS="['_foo','_bar']"`
  * 或在函数上加 `EMSCRIPTEN_KEEPALIVE`

若想要 C++ 与 JS 保持类与实例语义，可使用 **Embind**。

---

## 9. 调试与安全辅助

* `-g4`    —— 生成完整 source-map；浏览器 DevTools 能单步到 C++。
* `-sSAFE_HEAP=1`—— 越界/非法 free 检测，运行时会断点并打印栈。
* `-sASSERTIONS=2` —— 开启更多运行时断言。
* `EM_LOG=1`  —— 让 `printf` 直接写进浏览器控制台。

### 速记

> **编译**：`emcc hello.c -O2 -o hello.js`
> **调用**：`Module.ccall('add', 'number', ['number','number'], [1,2])`
> **调试**：`-g4 -sSAFE_HEAP=1`
> **体积**：`-Oz --closure 1` + Brotli/Gzip
> **互调**：`EMSCRIPTEN_KEEPALIVE` / `cwrap` / `Embind`
