TOC
Open TOC
ref
十分钟搞懂 WebAssembly
为什么说 WASM 是 Web 的未来
Emscripten 使用入门
setup
首先需要安装 Emscripten
Emscripten 能够帮助我们将 C/C++ 代码编译为 WebAssembly 代码,同时帮助我们生成部分所需的 JavaScript 胶水代码
最简单的用法就是让 Emscripten 执行一段 C/C++ 代码,考虑如下一段代码
使用如下的命令编译,story
为一个文本文件
其中 --preload-file
会在编译时将文件打包进 Emscripten 虚拟出的内存文件系统中,以供代码进行 I/O 操作
https://emscripten.org/docs/porting/files/packaging_files.html#packaging-using-emcc
使用 js runtime 运行上述程序
上述代码的输出会输出在 console 中
另外也可以部署生成的 html 模板文件,其中会模拟出一个 terminal 显示相同的内容
cmake
为了与之前的项目对接,使用 cmake 构建出 wasm 和 js 代码,CMakeLists.txt
如下
主要关注链接阶段的命令行选项
--preload-file
上文已经讲解过了
EXPORTED_FUNCTIONS
配置在编译时需要暴露的函数,注意开头需要加上一个下划线,Init
和 ExecuteQuery
是业务部分的接口,free
则是标准库函数,用于释放 allocateUTF8
动态分配的内存
EXPORTED_RUNTIME_METHODS
配置在运行时需要暴露的函数,此处可以参考 Interacting with code
在 build 文件夹下使用如下命令构建
然后是封装好的 C/C++ 代码接口,以 Init
为例,为了避免 name mangling,需要使用 extern "C"
最后是 html 文件,为了能够自定义 web shell,我们需要手写 html 文件,其中通过 JavaScript 胶水代码调用封装好的 C/C++ 代码接口
此处参考了 BusTub web shell,利用 jquery.terminal 模拟 terminal
比较 tricky 的地方 JS 代码如何调用 C++ 代码
此处使用 cwrap
将 C++ 导出函数封装为 JS 函数
参数含义如下
- ident 导出函数的函数名,不含下划线前缀
- returnType 导出函数的返回值类型
- argTypes 导出函数的参数类型的数组
实际上 ExecuteQuery
的函数签名如下
- 一方面,从终端中获取到 input 后,直接传入
ExecuteQuery
ccall
和 cwrap
封装函数会自动负责内存分配和释放问题,将 JS 字符串类型转换为 char *
类型
- 另一方面,需要手动使用
allocateUTF8
方法动态分配内存,并使用 UTF8ToString
将 char *
类型转换为 JS 字符串类型,最后回收内存
- 观察
cwrap
的对应参数类型为 number
而非 string
,可能原因是 cwrap
会在栈上分配相应的空间,为了避免爆栈,需要手动管理内存
- 另外,JS 与 C++ 相互调用的时候,参数与返回值本质上都是
Number
类型
- 注意最后一个参数为 u64 类型,否则无法进行无损类型转换,实际会发生传入的参数总为 0 的情形
- 此处大量参考了 https://cntofu.com/book/150/zh/ch2-c-js/readme.md
deploy
考虑使用 server-static 进行部署
编写配置文件 static-server.config.js
如下
然后键入 server-static
即可
部署在云服务器上,只需要如下文件
然后键入
欢迎游玩 FAT12 Shell 🤣 (deprecated)
todo