c++oding="utf-8" ?>
启用wasi需编译时指定--sysroot并添加--no-entry等链接选项;std::filesystem不可用因其底层调用返回enosys;文件读写依赖runtime挂载路径;http等能力需通过自定义导入函数实现。

WASI 接口在 C++ WebAssembly 中怎么启用
WASI 不是默认开启的,编译时没显式启用,openat、read、clock_time_get 这些函数链接会失败,运行时报 undefined symbol: __wasi_path_open 之类错误。
用 wasm-ld 或 clang++ 编译时必须加 --sysroot 指向 WASI sysroot,并传 -mwasm-exceptions(可选,但缺它可能 crash)、--no-entry(避免默认 _start 冲突):
clang++ -O2 -target wasm32-wasi \ --sysroot=/opt/wasi-sdk/share/wasi-sysroot \ -Wl,--no-entry -Wl,--export-all \ main.cpp -o main.wasm
- WASI SDK 版本要和运行时(如 wasmtime / wasmedge)对齐,wasi-sdk 20+ 生成的模块在旧 wasmtime 里可能报
unknown import -
--export-all不是必须,但不导出函数就调不动;若只导出特定函数,得用-Wl,--export=foo - 不用
-fno-rtti -fno-exceptions也行,但开了能减小体积、避免 trap;WASI 环境不支持 C++ 异常传播到 host
std::filesystem 在 WASI 下为什么直接崩
因为 std::filesystem 依赖底层系统调用(如 stat、opendir),而 libc++ 的 WASI 实现里这些函数是 stub(返回 ENOSYS),一调就 abort。
别碰 std::filesystem,改用 WASI 原生 API 或轻量封装:
- 用
__wasi_path_open+__wasi_fd_read手动读文件,头文件是<wasi></wasi>(需确保 sysroot 包含) - 如果用 wasi-libc,
fopen/fread是可用的,但路径只能是预挂载目录(如/work),且必须在 runtime 启动时用--dir=/host/path:/work显式挂载 -
getcwd()返回"/",chdir()无效 —— WASI 没有工作目录概念,所有路径都是挂载点相对路径
WASI 模块怎么读写宿主机文件
不是“自动能读”,而是靠 runtime 启动时用 --dir 或 --mapdir 把宿主机路径映射进来,模块里用的路径必须匹配映射后的虚拟路径。
例如这样启动:
wasmtime --dir=.:/app main.wasm
那 C++ 里就得写 fopen("/app/config.json", "r"),写成 "./config.json" 或 "config.json" 都打不开。
- 多个挂载点可叠加:
--dir=/tmp:/tmp --dir=$HOME/data:/data,模块内分别访问/tmp/xxx和/data/yyy -
--mapdir更严格:把宿主机/home/alice映射为模块内/home,但模块不能访问/home外的任何路径(沙箱更强) - 没挂载的路径一律
ENOENT,不会静默失败;mkdir在只读挂载点上会返回EACCES
如何从 C++ 主动调用宿主机能力(比如发 HTTP)
WASI 标准接口不包含网络,socket、connect 全部不可用。想发 HTTP,只能走「自定义导入函数」这条路。
步骤很明确:在 C++ 里声明 extern “C” 函数,编译时保留符号,然后 runtime 加载时把 host 函数注入进去:
extern "C" int http_request(const char* url, char* out_buf, size_t buf_len);
编译时不链接实现,只留一个未定义符号;运行时用 wasmtime 的 Func::new 注入回调。
- 参数必须是 POD 类型(
int、char*、size_t),不能传std::string或引用 - 字符串内存管理要小心:host 分配的 buffer,C++ 模块要用
__builtin_wasm_memory_grow或提前申请足够空间;反过来,C++ 分配的 buffer 要确保生命周期覆盖 host 调用 - 这种导入方式绕过了 WASI 安全模型,相当于手动开后门,权限控制得靠 runtime 层做(比如只允许特定域名)
真正麻烦的从来不是怎么写那几行 __wasi_fd_read,而是挂载路径写错、sysroot 版本不匹配、或者以为 std::filesystem 能用结果一运行就 abort —— 这些地方没提示,只给你一个 trap。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











