在 WebAssembly 中写入文件

Write to file within WebAssembly

我有下面的 C 代码,可以编译成 WebAssembly

# include <stdio.h>

int main() {

FILE *f = fopen("file.txt", "w");
if (f == NULL)
{
            printf("Error opening file!\n");
            return 0;
}

/* print some text */
const char *text = "Write this to the file";
fprintf(f, "Some text: %s\n", text);

/* print integers and floats */
int i = 1;
float py = 3.1415927;
fprintf(f, "Integer: %d, float: %f\n", i, py);

char c = 'A';
fprintf(f, "A character: %c\n", c);

fclose(f);

return 0;

}

所以我使用下面的命令生成一个wasm文件和相应的js文件:

emcc write.c -s WASM=1 -o write.html

然而,当我尝试使用 JS 引擎(如 v8)来执行这段代码时,我根本找不到生成的输出。我也没有收到任何错误:

➜  test_code ~/v8/v8/out/x64.release/d8 write.js
➜  test_code 

所以根据我的理解,wasm 代码需要利用 JS 来使用一些与系统相关的功能,比如 I/O 相关的运算符。也许在这个浏览器环境中可能不允许 "manipulate" 文件系统?因为通常在浏览器内部发生的事情,它应该留在浏览器内。

所以我写信询问将文件I/O相关的C程序迁移到WebAssembly环境的最佳实践。任何评论将不胜感激。谢谢。

d8 确实有一个 write 函数(v8/src/d8.cc?l=1706) for I/O write, but Emscripten's shell.js never uses it for simple JS shells. You will need some hacking in Emscripten's code if you want it to work in simple JS shells. Try exploring emscripten/src/library_fs.js.

编辑:刚刚意识到 d8 的 write 功能仅 print to stdout,所以它不是您想要的。看起来从简单的 JS shell 写入文件是不可能的(它们只是供 JS 引擎开发人员测试的东西)。

我没有验证这一点,但我认为 I/O 编写 运行 中的测试代码时可能会开箱即用 Node.js.

后续问题:

Emscripten 通过预处理和连接 shell.jspreamble.jspostamble.js 和编译时从 emscripten.py and compiler.js 生成的一些代码来生成 JS 包装器代码。 JS代码的预处理使用了C风格的预处理器(#if#else)加上一些{{{ }}},这就是Emscripten的JS代码看起来很搞笑的原因。

很多C函数都是用C和JS一起实现的。它的 C 部分直接链接到 WebAssembly(参见它们的实现 here), JS-part of it are implemented in library_*.js under here.

目前,Chrome 是唯一具有 Web FileSystem API. Google and Mozilla is currently working on standardizing Writable Files API. The first reaction most people have will be "this is a bad idea", but since browsers already allow executing untrusted code in user system (in a sandbox), writing files is probably not the most dangerous thing browser can do (https://twitter.com/ericlaw/status/1066149633855053825) 的浏览器。