我有一个C ++项目,我已使用emscripten将其转换为javascript。我需要有关通过节点将文件输入到程序中的帮助。据我了解,emscripten中的默认文件系统使用只能在网页或网络工作者上完成的预加载数据。我需要我在命令行上使用node.js。
[查看documentation,我发现有一种方法可以使用NODEFS代替默认的MEMFS,这应该允许我执行此操作。但是,我不确定该怎么做。我不太了解所提供的测试代码。
以下是原始C ++项目中文件处理的方式:
void InputFile(std::string &fileName)
{
std::ifstream in(fileName);
if (in.fail())
{
std::cerr << "ERROR, Could not open " << fileName << std::endl;
exit(1);
}
}
但是当我尝试使用文件运行转换后的程序时,node project.js -f test.file
会收到错误消息:ERROR, Could not open test.file
表示打开文件失败。原始的C ++项目能够打开文件而没有任何问题,因此我知道文件本身没有问题。
我不确定要使转换后的项目与文件输入一起使用该做什么,非常感谢您的帮助。
WebAssembly模块,使用emscripten构建,没有有关物理文件系统中文件的信息。而是使用虚拟文件系统。您要做的就是在物理系统上的文件与模块虚拟系统上的文件之间创建链接。 NODEFS给您这个机会。
我们将通过使用嵌入式JS代码(带有EM_ASM)在物理文件系统和虚拟文件系统之间添加上述链接,开始修改您的C ++代码。首先(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模块中,我们使用的是虚拟文件系统,而不是物理文件系统,所以当前目录(根目录'.'
)中的每个引用文件实际上都位于先前链接的虚拟目录中([C0 ])。因此,'/temp'
目录在该引用文件的名称之前:'/temp'
。
最后,我们可以编译该文件。我们强制进行同步编译(以确保std::ifstream in(std::string("/temp/") + fileName);
及时加载WASM模块)。此外,选项require
确保C ++命令-s EXIT_RUNTIME=1
完成执行。另外,我们需要链接exit(1);
(Embind)和NODEFS(--bind
):
-lnodefs.js
要使用与您提到的相同的调用约定来测试WebAssembly模块,我们可以使用以下emcc project.cpp -o project.js -s WASM_ASYNC_COMPILATION=0 -s EXIT_RUNTIME=1 --bind -lnodefs.js
脚本:
test.js
要运行文件,您所需要做的就是: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
的代码以提取InputFile
所在的目录,然后相应地安装实际到虚拟的目录。