{
  "schemaVersion": "0.11.0",
  "canonical": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism/",
  "atlas": "https://www.pystone.net/?node=emscripten-cpp-to-wasm-mechanism#knowledge-atlas",
  "markdown": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism.md",
  "context": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism.context.json",
  "knowledgeVersion": "224c990773de.5fa8af6e39fa",
  "build": {
    "siteCommit": "224c990773de166d23a886306577dd90379529ce",
    "notesCommit": "5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a",
    "builtAt": "1970-01-01T00:00:00.000Z",
    "version": "224c990773de.5fa8af6e39fa"
  },
  "id": "note:emscripten-cpp-to-wasm-mechanism",
  "slug": "emscripten-cpp-to-wasm-mechanism",
  "title": "Emscripten-C++到WebAssembly编译机制",
  "type": "note",
  "visibility": "public",
  "idStability": "rename-stable",
  "author": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "publisher": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "aliases": [],
  "summary": "Emscripten C++到WebAssembly编译机制 1. 它是什么",
  "contentRole": "unspecified",
  "isMoc": false,
  "mocRecognition": "none",
  "generated": false,
  "attribution": "unspecified",
  "domain": "10-计算机、信息技术与工程",
  "tags": [],
  "mocs": [],
  "contentHash": "10b1130bf77450a7b65cb7ce355af3d6fb8139f9ec95182f0480d9014af1e557",
  "assets": [],
  "headings": [
    {
      "depth": 1,
      "text": "Emscripten-C++到WebAssembly编译机制",
      "anchor": "emscripten-c到webassembly编译机制",
      "citation": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism/#emscripten-c%E5%88%B0webassembly%E7%BC%96%E8%AF%91%E6%9C%BA%E5%88%B6"
    },
    {
      "depth": 2,
      "text": "1. 它是什么",
      "anchor": "1-它是什么",
      "citation": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism/#1-%E5%AE%83%E6%98%AF%E4%BB%80%E4%B9%88"
    },
    {
      "depth": 2,
      "text": "2. 产物长什么样",
      "anchor": "2-产物长什么样",
      "citation": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism/#2-%E4%BA%A7%E7%89%A9%E9%95%BF%E4%BB%80%E4%B9%88%E6%A0%B7"
    },
    {
      "depth": 2,
      "text": "3. 运行时的三种组织方式",
      "anchor": "3-运行时的三种组织方式",
      "citation": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism/#3-%E8%BF%90%E8%A1%8C%E6%97%B6%E7%9A%84%E4%B8%89%E7%A7%8D%E7%BB%84%E7%BB%87%E6%96%B9%E5%BC%8F"
    },
    {
      "depth": 2,
      "text": "4. 双向调用：让 C 和 JS 互相干活",
      "anchor": "4-双向调用让-c-和-js-互相干活",
      "citation": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism/#4-%E5%8F%8C%E5%90%91%E8%B0%83%E7%94%A8%E8%AE%A9-c-%E5%92%8C-js-%E4%BA%92%E7%9B%B8%E5%B9%B2%E6%B4%BB"
    },
    {
      "depth": 2,
      "text": "9. 调试与安全辅助",
      "anchor": "9-调试与安全辅助",
      "citation": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism/#9-%E8%B0%83%E8%AF%95%E4%B8%8E%E5%AE%89%E5%85%A8%E8%BE%85%E5%8A%A9"
    },
    {
      "depth": 3,
      "text": "速记",
      "anchor": "速记",
      "citation": "https://www.pystone.net/notes/emscripten-cpp-to-wasm-mechanism/#%E9%80%9F%E8%AE%B0"
    }
  ],
  "claims": [],
  "outgoing": [],
  "incoming": [
    {
      "id": "note:game-graphics-and-runtime",
      "title": "游戏图形与运行时",
      "url": "https://www.pystone.net/notes/game-graphics-and-runtime/",
      "atlas": "https://www.pystone.net/?node=game-graphics-and-runtime#knowledge-atlas",
      "label": "游戏图形与运行时",
      "origin": "explicit",
      "humanReviewed": true,
      "context": "WebGL中的“Emscripten-C++到WebAssembly编译机制”导航项",
      "citation": "https://www.pystone.net/notes/game-graphics-and-runtime/#webgl"
    }
  ],
  "contentMarkdown": "# Emscripten-C++到WebAssembly编译机制\n## 1. 它是什么\n\nEmscripten 是基于 LLVM 的 **C/C++→WebAssembly** 交叉编译器。\n常用入口命令：\n\n* `emcc`  – C 源文件 → WebAssembly\n* `em++`  – C++ 源文件 → WebAssembly\n\n---\n\n## 2. 产物长什么样\n\n一次编译通常会生成两份文件：\n\n1. `xxx.wasm` — 二进制指令，真正运行在浏览器 / Node 的模块\n2. `xxx.js`  — 运行时与胶水代码，负责加载 WASM、补充系统调用、导出接口\n\n用 `-o out.js` 就会同时写出 `out.wasm`。\n\n---\n\n## 3. 运行时的三种组织方式\n\n| 模式               | 触发方式                               | 用途                                       |\n| ---------------- | ---------------------------------- | ---------------------------------------- |\n| **单 JS 文件（默认）**  | 不额外设置                              | 最易上手；`out.js` 自动拉取 `out.wasm`            |\n| **模块化输出**        | `-sMODULARIZE=1 -sEXPORT_ES6=1`    | 把运行时包装成 ES6 Module / UMD，便于与打包工具集成       |\n| **纯 Wasm “独立式”** | `-sSTANDALONE_WASM`（曾用 `-sWASM=2`） | 让 `.wasm` 拥有完整入口表，只需极简 JS 引导即可；适合非 JS 宿主 |\n\n---\n\n## 4. 双向调用：让 C 和 JS 互相干活\n\n* **JS → C**\n  * `cwrap` / `ccall` 在运行时直接调用导出的 C 函数。\n* **C → JS**\n  * 把 JS 函数挂到 `Module` 或通过 `EM_JS`/`emscripten_run_script` 暴露。\n  * **怎样让符号“被看见”**\n\n  * 编译时列入 `-sEXPORTED_FUNCTIONS=\"['_foo','_bar']\"`\n  * 或在函数上加 `EMSCRIPTEN_KEEPALIVE`\n\n若想要 C++ 与 JS 保持类与实例语义，可使用 **Embind**。\n\n---\n\n## 9. 调试与安全辅助\n\n* `-g4`    —— 生成完整 source-map；浏览器 DevTools 能单步到 C++。\n* `-sSAFE_HEAP=1`—— 越界/非法 free 检测，运行时会断点并打印栈。\n* `-sASSERTIONS=2` —— 开启更多运行时断言。\n* `EM_LOG=1`  —— 让 `printf` 直接写进浏览器控制台。\n\n### 速记\n\n> **编译**：`emcc hello.c -O2 -o hello.js`\n> **调用**：`Module.ccall('add', 'number', ['number','number'], [1,2])`\n> **调试**：`-g4 -sSAFE_HEAP=1`\n> **体积**：`-Oz --closure 1` + Brotli/Gzip\n> **互调**：`EMSCRIPTEN_KEEPALIVE` / `cwrap` / `Embind`\n"
}
