一个受虐狂的 Web 开发指南

这是一篇关于使用 Emscripten 将 C/C++代码构建为可在 Web 浏览器中运行的 Web 应用程序的教程文章,主要内容总结如下:

  • 介绍:作者通过将自己的魔方最优求解器转换为 Web 应用程序,学习了使用 Emscripten 将 C 代码编译为 WebAssembly 并与 JavaScript 和 HTML 结合的过程,介绍了使用 WebAssembly 的原因,以及该教程不适合初学者,适合 C/C++开发者将程序或库移植到 Web 的情况。
  • 设置环境:教程示例包含在 git 仓库中,需要安装 Emscripten(包含 Node.js)和 web 服务器(如 darkhttpd 或 Python 的http.server包),作者仅在 Linux 上测试过,Windows 用户可在 WSL 中运行或调整示例。
  • Hello World:编译简单的 C 代码hello.c为 Web 应用程序,生成index.htmlindex.wasmindex.js文件,可在浏览器或终端中运行,展示了基本的编译和运行过程。
  • 中间环节 I:WebAssembly 是什么:介绍了 WebAssembly 是一种在 Web 浏览器虚拟机中运行的低级语言,动机是提供接近原生的性能,早期 Emscripten 将 C/C++代码编译为 JavaScript 的子集 asm.js,WebAssembly 有文本表示形式,2025 年初之前是 32 位架构,目前 Firefox 和 Chrome 支持 64 位指针的 WASM64 标准。
  • 构建库:将 C 库编译为 WebAssembly 并从 JavaScript 调用,使用emcc命令生成library.jslibrary.wasm文件,需要指定要导出的函数,使用onRuntimeInitialized回调函数处理异步初始化,展示了简单库的构建和调用过程。
  • 中间环节 II:JavaScript 和 DOM:介绍了 JavaScript 与文档对象模型(DOM)的交互,通过getElementByIdinnerText等方法访问和修改 HTML 元素的内容,还展示了如何在 HTML 中加载外部 JavaScript 脚本,并使用defer属性确保脚本在页面加载完成后执行。
  • 加载库并使其成为模块:构建模块化的库,使用emcc-sMODULARIZE-sEXPORT_NAME等选项生成library.mjs文件,在 Node.js 和浏览器中使用模块的方式不同,需要注意文件扩展名和服务器配置,展示了模块化库的构建和使用方法。
  • 多线程:将多线程应用程序移植到 Web,使用 pthreads 实现并行计算,在浏览器中运行多线程代码需要设置Cross-Origin-Opener-PolicyCross-Origin-Embedder-PolicyHTTP 头,展示了多线程程序的构建和运行。
  • 中间环节 III:Web Workers 和 Spectre:介绍了 Web Workers 是与主网页进程分离的进程,用于在后台运行慢操作而不阻塞 UI 线程,Web Workers 与主进程的内存隔离,Spectre 漏洞导致浏览器需要安全上下文和跨源隔离才能使用SharedArrayBuffer,需要设置Cross-Origin-*头。
  • 不要阻塞主线程!:通过 Web Worker 解决多线程计算阻塞主线程的问题,主脚本负责与用户交互和发送计算请求,Worker 负责计算并返回结果,展示了使用 Web Worker 优化多线程程序的方法。
  • 回调函数:实现接受另一个函数作为参数的库函数,在 JavaScript 中通过addFunctionUTF8ToString等 Emscripten 函数将 JavaScript 函数转换为 C 函数指针,展示了回调函数的使用方法和相关编译器标志的设置。
  • 持久存储:通过使用 IndexedDB API 将数据持久存储在浏览器的缓存中,介绍了 Emscripten 的文件系统 API 及其不同的后端,使用--lidbfs.js编译器选项激活IDBFS后端,通过 JavaScript 代码设置和同步虚拟文件系统,展示了如何在 Web 应用程序中实现持久存储。
  • 总结思考:作者讨论了在使用 Emscripten 构建 Web 应用程序过程中所学的知识,包括一些 C++特定的功能,如EMBIND()emscripten::val,并总结了对抽象的理解,即所有抽象都有泄漏,Emscripten 虽然抽象了 Web 相关的细节,但在代码复杂度增加时仍需要了解底层系统。
阅读 11
0 条评论