2013-04-12 46 views
4

我有一個C++函數,曾經調用過從stdin輸入的消息。使用emscripten將此函數導出爲javascript會導致調用window.prompt。如何將emscripten瀏覽器的輸入法從window.prompt更改爲更明智的東西?

與瀏覽器提示互動是一項非常繁瑣的任務。首先你可以在一次只粘貼一行。其次,指示EOF的唯一方法是按'取消'。最後但並非最不重要的唯一方法(在我的功能的情況下),使其停止要求用戶輸入window.prompt是通過檢查複選框,防止更多的提示彈出。

對我來說,最好的輸入方法是讀取一些blob。我知道我可以破解library.js,但我看到一些問題:

  1. 讀取blob是異步的。
  2. 要讀取blob,首先必須打開一個文件,用戶必須先選擇一個文件。
  3. 我真的不知道如何防止我的函數永遠讀這個blob - 有沒有像window.prompt複選框,我不知道如果發現EOF將停止它,如果它不在window.prompt大小寫(只檢查複選框幫助)。

最好的解決方案是某種回調,但我希望看到更多有經驗的用戶提供的sime提示。

+0

請說明您正在處理什麼類型的輸入以及您的應用程序的一般想法。 – abergmeier

+1

INCHI圖書館:http://www.iupac.org/home/publications/e-resources/inchi/download.html,對於計算化學非常重要。輸入是molfile:http://en.wikipedia.org/wiki/Structure_data_file#Molfile我試圖從命令行程序inchi-1中導出'process_single_input'方法,您可以從第一個鏈接。 – mnowotka

+0

你可以查看我到目前爲止在這裏:http://mnowotka.kei.pl/inchi/ 要在JavaScript控制檯中運行導出的函數類型: bla = Module.cwrap('process_single_input','string','string ')\ n bla('bla -STDIO') – mnowotka

回答

1

據我瞭解,你可以嘗試以下方法:

  1. 實現通過JavaScript Blob界面中選擇一個JavaScript文件和訪問它。
  2. 分配一些內存Emscripten

    var buf = Module._malloc(blob.size); 
    
  3. 寫您Blob的內容轉換成從Javascript返回的內存位置。

    Module.HEAPU8.set(new Uint8Array(blob), buf); 
    
  4. 通行證該存儲器位置到第二Emscripten編譯函數,然後處理該文件內容和

  5. 解除分配所分配的存儲器。

    Module._free(buf); 
    

最佳閱讀the wiki第一。

+0

第一點很簡單。你有沒有第二點和第三點的例子? – mnowotka

+1

在wiki中添加了一些示例。 – abergmeier

0

一種方法是使用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); 
    } 
}; 

注(如你暗示),由於讀者的異步性,有可能是一個競爭條件:讀者必須加載然後才能預期標準輸入的數據。您可能需要實施一些機制來避免這種情況。根據您的具體要求,你可以把這樣Emscripten程序實際上並不叫main(),直到你擁有的數據:

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(); 
    } 
} 

注:這是我在Providing stdin to an emscripten HTML program?回答的一個版本,但重點標準輸入,並添加關於從Blob傳遞數據的部分。

相關問題