How to change emscripten browser input method from window. Something more reasonable?

I have a C ++ function that was once called consuming input from stdin. Exporting this function to javascript using emscripten calls window.prompt calls.

Interacting with a browser prompt is a really tedious task. First of all, you can insert only one row in time. Secondly, the only way to specify EOF is to click cancel. And last but not least, the only way (in the case of my function) is to force the user to stop asking the user to enter window.prompt by checking the box to prevent the tooltips from popping up.

For me, the best input method would be to read some blob. I know I can hack library.js, but I see some problems:

  • Reading blob is asynchronous.
  • To read blob, you first need to open the file that the user must select first.
  • I really don’t know how to prevent my function from reading this blob forever - there is no flag, for example, with window.prompt, and I'm not sure if EOF detection will stop it if it was not in window.prompt (only the flag is checked).

A better solution would be some kind of callback, but I would like to see sime hints from more experienced users.

+4
source share
2 answers

From what I understand, you can try the following:

  • Implementing file selection in Javascript and accessing it through the Javascript Blob interface.
  • Allocate some memory in Emscripten

     var buf = Module._malloc( blob.size ); 
  • Write the contents of your Blob to the returned memory cell from Javascript.

     Module.HEAPU8.set( new Uint8Array(blob), buf ); 
  • Pass this memory cell to the second compiled Emscripten function, which then processes the contents of the file and

  • Discard allocated memory.

     Module._free( buf ); 

It’s best to read the wiki first.

+1
source

You can use the Emscripten Filesystem API, for example, by calling FS.init in the PreRun function of the module, passing the user as standard input.

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

The function is pretty low-level: you have to deal with one character at a time. To read some data from blob, you can do something like:

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

Note (as you hinted), due to the asynchronous nature of the reader, there may be a race condition: the reader had to load before you could expect data on standard input. You may need to implement some mechanism to avoid this in the real case. Depending on your exact requirements, you can make Emscripten actually not call main() until you have data:

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

Note: is this a variant of my answer on Providing stdin for the emscripten HTML program? but with a focus on standard input and adding parts about transferring data from Blob.

0
source

All Articles