7

我有一个 C++ 函数,它曾经被调用消耗来自标准输入的输入。使用 emscripten 将此函数导出到 javascript 会导致调用 window.prompt。

与浏览器提示交互确实是一项繁琐的任务。首先,您一次只能粘贴一行。其次,指示 EOF 的唯一方法是按“取消”。最后但并非最不重要的唯一方法(在我的函数的情况下)使其停止通过 window.prompt 要求用户输入是通过选中复选框以防止弹出更多提示。

对我来说,最好的输入法是阅读一些 blob。我知道我可以破解 library.js,但我发现了一些问题:

  1. 读取 blob 是异步的。
  2. 要读取 blob,首先您必须打开一个用户必须先选择的文件。
  3. 我真的不知道如何阻止我的函数永远读取这个 blob - 没有像 window.prompt 这样的复选框,我不确定如果在 window.prompt 情况下没有发现 EOF 是否会阻止它(仅检查复选框有帮助)。

最好的解决方案是某种回调,但我希望从更有经验的用户那里看到一些提示。

4

2 回答 2

1

据我了解,您可以尝试以下操作:

  1. 实现在 Javascript 中选择文件并通过 JavascriptBlob接口访问它。
  2. 在Emscripten中分配一些内存

    var buf = Module._malloc( blob.size );
    
  3. 将您的内容写入BlobJavascript 返回的内存位置。

    Module.HEAPU8.set( new Uint8Array(blob), buf );
    
  4. 将该内存位置传递给第二个Emscripten编译函数,该函数然后处理文件内容并

  5. 释放分配的内存。

    Module._free( buf );
    

最好先阅读wiki

于 2013-04-13T15:32:12.590 回答
1

一种方法是使用 Emscripten 文件系统 API,例如在 Module preRun 函数中调用FS.init,将自定义函数作为标准输入传递。

var Module = {
  preRun: function() {
    function stdin() {
      // Return ASCII code of character, or null if no input
    }

    var stdout = null; // Keep as default
    var stderr = null;  // Keep as default
    FS.init(stdin, stdout, stderr);
  }
};

该功能非常低级:一次必须处理一个字符。要从 blob 中读取一些数据,您可以执行以下操作:

var data = new Int8Array([1,2,3,4,5]);
var blob = new Blob([array], {type: 'application/octet-binary'});
var reader = new FileReader();
var result;
reader.addEventListener("loadend", function() {
  result = new Int8Array(reader.result);
});
var i = 0;
var Module = {
  preRun: function() {
    function stdin() {
      if (if < result.byteLength {
        var code = result[i];
        ++i;
        return code;
      } else {
        return null;
      }
    }

    var stdout = null; // Keep as default
    var stderr = null; // Keep as default
    FS.init(stdin, stdout, stderr);
  }
};

注意(正如您所暗示的),由于阅读器的异步特性,可能存在竞争条件:阅读器必须已加载,然后您才能在标准输入中预期数据。在实际情况下,您可能需要实现一些机制来避免这种情况。main()根据您的确切要求,您可以这样做,以便 Emscripten 程序在您拥有数据之前不会实际调用:

var fileRead = false;
var initialised = false;
var result;

var array =  new Int8Array([1,2,3,4,5]);
var blob = new Blob([array], {type: 'application/octet-binary'});
var reader = new FileReader();
reader.addEventListener("loadend", function() {
   result = new Int8Array(reader.result);
   fileRead = true;
   runIfCan();
});
reader.readAsArrayBuffer(blob);

var i = 0;
var Module = {
   preRun: function() {
      function stdin() {
         if (i < result.byteLength)
         {
            var code = result[i];
            ++i;
            return code;
         } else{
            return null;
         }
      }

      var stdout = null;
      var stderr = null;
      FS.init(stdin, stdout, stderr);
      initialised = true;
      runIfCan();
   },
   noInitialRun: true
};

function runIfCan() {
   if (fileRead && initialised) {
      // Module.run() doesn't seem to work here
      Module.callMain();
   }
}

注意:这是我在为 emscripten HTML 程序提供标准输入的答案的一个版本?,但重点关注标准输入,并添加有关从 Blob 传递数据的部分。

于 2015-10-15T14:36:06.693 回答