解释
网络组装 https://webassembly.org/模块,使用构建埃姆脚本 https://emscripten.org/,没有有关物理文件系统中文件的信息。相反,它使用虚拟文件系统。您所要做的就是在物理系统上的文件与模块虚拟系统上的文件之间创建链接。NODEFS https://emscripten.org/docs/api_reference/Filesystem-API.html#filesystem-api-nodefs给你这个机会。
快速解决方案
我们将开始修改您的 C++ 代码,通过使用嵌入式 JS 代码(使用EM_ASM https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#interacting-with-code-call-javascript-from-native)。首先(1),我们创建一个目录'/temp'
在所有引用文件所在的虚拟文件系统上。然后(2),我们将这个新的虚拟目录与真实的物理位置(当前工作目录)链接'.'
) 其中所有引用的文件都已存在。
#include <emscripten.h>
#include <emscripten/bind.h>
#include <iostream>
#include <fstream>
void InputFile(const std::string &fileName)
{
EM_ASM(
FS.mkdir('/temp'); // (1)
FS.mount(NODEFS, {root : '.'}, '/temp');); // (2)
std::ifstream in(std::string("/temp/") + fileName);
if (in.fail())
{
std::cerr << "ERROR, Could not open " << fileName << std::endl;
exit(1);
}
}
EMSCRIPTEN_BINDINGS(Module)
{
emscripten::function("InputFile", &InputFile);
}
现在,因为在 WebAssembly 模块中,我们正在使用虚拟文件系统,而不是物理文件系统,每个引用的文件都来自当前目录(根目录)'.'
)实际上位于先前链接的虚拟目录中('/temp'
)。因此,'/temp'
目录位于引用文件的名称之前:std::ifstream in(std::string("/temp/") + fileName);
.
最后,我们可以编译这个文件。我们强制同步编译(以确保require
按时加载 WASM 模块)。此外,选项-s EXIT_RUNTIME=1
确保 C++ 命令exit(1);
完成执行。另外,我们还需要链接Embind https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html (--bind
) and NODEFS https://emscripten.org/docs/api_reference/Filesystem-API.html#filesystem-api-nodefs (-lnodefs.js
):
emcc project.cpp -o project.js -s WASM_ASYNC_COMPILATION=0 -s EXIT_RUNTIME=1 --bind -lnodefs.js
Testing
要使用与您提到的相同的调用约定来测试 WebAssembly 模块,我们可以使用以下命令test.js
script:
var Module = require('./project.js');
if (process.argv[3] && process.argv[2] === '-f') {
const filename = process.argv[3];
Module.InputFile(filename);
} else {
console.log('Pass the file with -f flag!');
}
要运行该文件,您所要做的就是:node test.js -f test.file
Comment
如果引用的文件位于当前工作目录中,则此方法效果很好。如果不是,您可以修改以下代码InputFile
解压到其中的目录fileName
是,然后相应地挂载实目录到虚拟目录。