Предоставление стандартного ввода в HTML-программу emscripten?

У меня есть программа на C, которая принимает один аргумент (массив / строку char) через командную строку, а также читает из стандартного ввода. Я скомпилировал его в JavaScript с помощью emscripten. Это было успешно, и я могу запустить его так же, как обычную программу на C, используя node.js:

emcc -O2 translate.c
node translate.js "foo" < bar.txt

Как видите, я предоставляю строку "foo" в качестве аргумента, а содержимое bar.txt - в качестве stdin. Теперь я хочу, чтобы это был отдельный HTML-файл.

Изменяя вывод на HTML:

emcc -O2 translate.c -o trans.html

Я предоставляю аргумент, добавляяarguments: ['foo'], к определениям в var Module, Это работает, как и ожидалось, программа получает аргумент правильно.

Теперь, как мне предоставить ввод stdin для этой программы? Мне не нужно делать это динамически. Было бы хорошо просто объявить строку где-нибудь в HTML с требуемым содержимым stdin.

редактировать

Только что нашел решение, которое работает для меня. В файле JS для сгенерированного HTML есть обработчик ввода по умолчанию, который prompt()s пользователь, когда никакой другой метод ввода не определен. Просто отредактируйте переменную result или вызовите свою собственную функцию:

} else if (typeof window != 'undefined' &&
    typeof window.prompt == 'function') {
    // Browser.

    // REPLACE THIS CODE:
    result = window.prompt('Input: ');  // returns null on cancel
    if (result !== null) {
        result += '\n';
    }

3 ответа

Можно было бы использовать API файловой системы Emscripten, например, вызвав FS.init в функции preRun модуля, передавая пользовательские функции, которые будут использоваться для стандартного ввода, вывода и ошибки.

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

    function stdout(asciiCode) {
      // Do something with the asciiCode
    }

    function stderr(asciiCode) {
      // Do something with the asciiCode
    }

    FS.init(stdin, stdout, stderr);
  }
};

Функции довольно низкоуровневые: каждая из них имеет дело с одним символом за раз как с кодом ASCII. Если у вас есть строки, которые вы хотите передать, вам придется самим перебирать символы строки. Я подозреваю, что charCodeAt будет полезным. Для вывода строк из stdout или stderr, я подозреваю, что было бы полезно из CharCode.

Примеры (не очень хорошо протестированные!) Реализаций, использующих каждую, приведены ниже.

var input = "This is from the standard input\n";
var i = 0;
var Module = {
  preRun: function() {
    function stdin() {
      if (i < res.length) {
        var code = input.charCodeAt(i);
        ++i;
        return code;
      } else {
        return null;
      }
    }

    var stdoutBuffer = "";
    function stdout(code) {
      if (code === "\n".charCodeAt(0) && stdoutBuffer !== "") {
        console.log(stdoutBuffer);
        stdoutBufer = "";
      } else {
        stdoutBuffer += String.fromCharCode(code);
      }
    }

    var stderrBuffer = "";
    function stderr(code) {
      if (code === "\n".charCodeAt(0) && stderrBuffer !== "") {
        console.log(stderrBuffer);
        stderrBuffer = "";
      } else {
        stderrBuffer += String.fromCharCode(code);
      }
    }

    FS.init(stdin, stdout, stderr);
  }
};

Вместо того, чтобы редактировать вывод Emscripten, вы могли бы обезьяна исправить объект Window

window.prompt = function() {
  return 'This will appear to come from standard input';
};

Не удивительно, но я бы посчитал это менее взломанным, чем редактирование сгенерированного Emscripten Javascript.

По вопросу "Редактировать" я сделал свою функцию, спасибо.

Просто надеюсь, что приведенный ниже код может помочь кому-то еще.

  1. комментарий run(); в конце emscript

    // in my emscript 
    
    // shouldRunNow refers to calling main(), not run().
    var shouldRunNow = true;
    if (Module['noInitialRun']) {
        shouldRunNow = false;
    }
    //run(); // << here
    // {{POST_RUN_ADDITIONS}}
    
  2. result = areaInput(); // В качестве упомянутого вопроса

  3. добавьте приведенный ниже код в ваш HTML-файл, чтобы активировать run () в emscript

    <script>
    var message;
    var point = -1;
    function getArea(){
        message = document.getElementById('input').value.split('\n');
    }
    function areaInput(){
        if(point >= message.length - 1){
            return null;
        }
        point += 1;
        return message[point];
    }
    function execEmscript(){
        window.console = {
            log: function(str){
                document.getElementById("output").value += "\n" + str;
            }
        }
        getArea();
        run();
    }
    </script>
    
  4. помните io textareas в вашем html

    <textarea id="input" cols="80" rows="30"></textarea>

    <textarea id="output" cols="80" rows="30"></textarea>

  5. и кнопка

    <button onclick="execEmscript();">run</button>

Другие вопросы по тегам