WASI函数ABI规范及fd_write第四个参数与复杂Result返回问题
fd_write第四个参数的作用
WASI Snapshot Preview1 运行在标准Core WebAssembly之上,而当前版本的Core WASM仅支持单个返回值,无法直接承载Result<size, errno>的两种返回场景,因此对这类函数做了ABI适配:
你看到的fd_write四个入参依次对应:
- 第一个i32:目标文件描述符
fd - 第二个i32:
ciovec数组在WASM线性内存中的起始偏移 - 第三个i32:
ciovec数组的元素个数 - 第四个i32:输出参数指针,指向WASM线性内存中用于存放成功写入字节数的地址
正确的实现逻辑为:
- 写入操作成功时:你需要把实际写入的字节数按WASM小端序写入第四个参数指向的4字节内存区域,然后函数返回
0(对应WASI的SUCCESS错误码) - 写入操作失败时:不需要操作第四个参数指向的内存,直接返回对应的非0错误码即可
你之前遇到的两个问题都是实现不符合规范导致的:
- 调用
fd_write后被反复触发:是因为你没有向第四个参数指向的内存写入实际写入字节数,C标准库的printf读取到脏值/0值,判定写入未完成触发重试 - 直接返回写入字节数就能正常终止:属于巧合,刚好命中了emscripten编译的libc的兼容处理逻辑,不属于符合WASI规范的实现,实际运行其他程序会出现不可预期的错误。
复杂Result类型的ABI实现规则
WASI Snapshot Preview1对所有无法用单个i32承载的Result<T, E>类型,统一采用固定的ABI约定:
- 在函数入参列表末尾追加一个输出指针参数,指向WASM线性内存中用于存储
Ok(T)变体值的区域 - 函数返回值固定为i32类型的错误码:返回
0代表操作成功,此时运行时必须按照WASI规范定义的类型布局、对齐要求,将T的值完整写入输出指针指向的内存区域;返回非0代表操作失败,此时输出指针指向的内存内容未定义,无需写入 - 如果
T是复合结构体类型,你需要严格按照WASI规范定义的字段顺序、对齐规则逐字段写入对应内存。
内容的提问来源于stack exchange,提问作者Hellstorm
相关产品推荐
相关产品推荐

