如何使用emscripten通过node.js进行文件输入? [英] How to do file inputs via node.js using emscripten?

查看:190
本文介绍了如何使用emscripten通过node.js进行文件输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C ++项目,已使用emscripten将其转换为javascript.我需要有关通过节点将文件输入到程序中的帮助.据我了解,emscripten中的默认文件系统使用只能在网页或网络工作者上完成的预加载数据.我需要在命令行上使用node.js.

I have a C++ project that I have converted into javascript using emscripten. I need help with implementing file input into the program via node. As I understand it the default file system in emscripten uses preloaded data that can only be done on a web page or web worker. I need mine to work with node.js on the command line.

查看文档我看到有一种方法可以使用NODEFS代替默认的MEMFS,这应该允许我执行此操作.但是,我不确定该怎么做.我不太了解所提供的测试代码.

Looking at the documentation I see that there's a way to use NODEFS instead of the default MEMFS which should allow me to do this. However, I'm unsure how I'm supposed to go about this. I don't really understand the test code that's provided.

以下是原始C ++项目中文件处理的方式:

Here's how the file handling is being done in the original C++ project:

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,无法打开test.file 表示打开文件失败.原始的C ++项目能够打开文件而没有任何问题,因此我知道文件本身没有问题.

But when I attempt to run the converted program with a file, node project.js -f test.file I get the error message: ERROR, Could not open test.file meaning that opening the file failed. The original C++ project was able to open the file without any issues, so I know there's not problem with the file itself.

我不确定要使转换后的项目与文件输入一起使用需要做什么,非常感谢您.

I'm not sure what I have to do to make the converted project work with file inputs, any help would very much appreciated.

推荐答案

说明

WebAssembly 模块,该模块是使用 NODEFS 为您提供了这一机会.

Explanation

WebAssembly module, built using emscripten, has no information about files in your physical file system. Instead, it uses a virtual file system. All you have to do is to create a link between files on your physical system to the files on the module's virtual system. NODEFS gives you this opportunity.

我们将通过使用嵌入式JS代码(使用

We will start at modifying your C++ code by adding the aforementioned link between physical and virtual file systems using embedded JS code (with EM_ASM). First (1), we create a directory '/temp' on the virtual file system where all referenced files will be located in. Then (2), we link this new virtual directory with a real physical location (the current working directory '.') where all the referenced files are already.

#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);

Now, because in the WebAssembly module, we are working with the virtual file systems, and not the physical one, each referenced file from the current directory (the root '.') is actually in the virtual directory previously linked ('/temp'). Hence, '/temp' directory precedes the name to the referenced file: std::ifstream in(std::string("/temp/") + fileName);.

最后,我们可以编译这个文件.我们强制进行同步编译(以确保 require 准时加载WASM模块).此外,选项 -s EXIT_RUNTIME = 1 可确保C ++命令 exit(1); 完成执行.另外,我们需要链接嵌入(-bind )和 NODEFS (-lnodefs.js ):

Finally, we can compile this file. We force the synchronized compilation (to make sure the require loads the WASM module on time). Moreover, the option -s EXIT_RUNTIME=1 makes sure that the C++ command exit(1); finishes the execution. Also, we need to link Embind (--bind) and NODEFS (-lnodefs.js):

emcc project.cpp -o project.js -s WASM_ASYNC_COMPILATION=0 -s EXIT_RUNTIME=1  --bind -lnodefs.js

测试

要使用与您提到的相同的调用约定来测试WebAssembly模块,我们可以使用以下 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

To run the file, all you have to do is this: node test.js -f test.file

如果引用的文件位于当前工作目录中,则此方法效果很好.如果不是,则可以修改 InputFile 的代码以提取 fileName 所在的目录,然后挂载实际到虚拟目录

This approach works well if the referenced files are in the current working directory. In the case they are not, you could modify the code of the InputFile to extract the directory in which the fileName is, and then, mount the real-to-virtual directory accordingly.

这篇关于如何使用emscripten通过node.js进行文件输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆