7

一度呼び出されて stdin からの入力を消費する C++ 関数があります。emscripten を使用してこの関数を JavaScript にエクスポートすると、window.prompt が呼び出されます。

ブラウザのプロンプトを操作するのは、本当に退屈な作業です。まず、一度に 1 行しか貼り付けることができません。次に、EOF を示す唯一の方法は「キャンセル」を押すことです。最後になりましたが、(私の関数の場合) window.prompt による入力をユーザーに求めるのをやめる唯一の方法は、チェックボックスをオンにして、それ以上のプロンプトが表示されないようにすることです。

私にとって最良の入力方法は、ブロブを読み取ることです。library.js をハッキングできることはわかっていますが、いくつか問題があります。

  1. BLOB の読み取りは非同期です。
  2. BLOB を読み取るには、まず、ユーザーが最初に選択する必要があるファイルを開く必要があります。
  3. 関数がこのブロブを永遠に読み取らないようにする方法が本当にわかりません-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でコンパイルされた 2 番目の関数に渡します。これにより、ファイルの内容が処理され、

  5. 割り当てられたメモリの割り当てを解除します。

    Module._free( buf );
    

最初にウィキを読むのが最善です。

于 2013-04-13T15:32:12.590 に答える
1

Emscripten Filesystem API を使用する方法があります。たとえば、モジュールの 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);
  }
};

この関数は非常に低レベルです: 一度に 1 文字を処理する必要があります。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 プログラムに stdin を提供していますか?での私の回答のバージョンです。、ただし、標準入力に焦点を当て、Blob からのデータの受け渡しに関する部分を追加します。

于 2015-10-15T14:36:06.693 に答える