У меня есть проект C ++, который я компилирую в Javascript, используя emscripten. Это работает, однако, из-за ограничений ресурсов и по причинам интерактивности, я хотел бы запустить это внутри веб-работника.
Тем не менее, мой проект использует стандартный ввод. Я нашел способ предоставить свою собственную реализацию stdin, переписав Module [‘stdin’] с помощью функции, которая возвращает один символ за раз от общего stdin, и закрывается с 0 как EOF.
Это работает, когда скрипт выполняется внутри страницы, так как объект Module, представленный в html-файле, используется совместно со скриптом.
Когда вы работаете как веб-работник, этот объект модуля не является общим. Вместо этого, передача сообщений обеспечивает постоянную работу модуля. Это не включает ‘stdin’.
Я работал над этим путем изменения выходного JavaScript:
В коде:
Module['stdin_pointer'] = 0;
Module['stdin_content'] = "";
Module['stdin']=(function () {
if (Module['stdin_pointer'] < Module['stdin_content'].length) {
code = Module['stdin_content'].charCodeAt(Module['stdin_pointer']);
Module['stdin_pointer']=Module['stdin_pointer']+1;
return code;
} else {
return null;
}
});
external = function(message){
switch(message.data.target){
case 'stdin' : {
Module['idpCode'] = message.data.content;
removeRunDependency('stdin');
break;
}
default: throw 'wha? ' + message.data.target;
}
};
[...]
addRunDependency("stdin");
[...]
//Change this in the original onmessage function:
// default: throw 'wha? ' + message.data.target;
//to
default: {external(message);}
Понятно, что это & Часть c довольно проста, потому что ее можно добавить в начале (или около начала) файла js, но b & d (добавление ваших собственных зависимостей и получение вашего собственного обработчика сообщений в цикле) требует от вас редактирования встроенного кода.
Поскольку мой проект очень большой, поиск необходимых строк для редактирования может быть очень громоздким, и только в оптимизированном и минимизированном коде emscripten.
Автоматические сценарии для этого, а также сам обходной путь, вероятно, сломаются в новых выпусках emscripten.
Есть ли более хороший и правильный способ достичь того же поведения?
Спасибо!
//РЕДАКТИРОВАТЬ:
--separate-asm
flag очень полезен в том смысле, что файл, который я должен редактировать, теперь имеет всего несколько строк (в уменьшенном виде). Это значительно снижает нагрузку, но это все еще не совсем правильный путь, поэтому я не хочу отмечать это как решенное.
Единственный известный мне способ достижения того, чего вы хотите, — это не использовать рабочий API, предоставляемый Emscripten, а использовать свой собственный. Все детали, вероятно, выходят за рамки одного вопроса, но на высоком уровне вам нужно …
Скомпилируйте рабочий модуль с вашим кодом обработки, но без использования флага BUILD_AS_WORKER
Как на пользовательском интерфейсе, так и на рабочем месте вам нужно будет написать код JavaScript для взаимодействия в / из миров C ++, используя один из методов: http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html, который затем напрямую вызывает рабочий API-интерфейс JavaScript https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
На рабочей стороне этого вы сможете управлять объектом Module, устанавливая stdin по своему усмотрению.
В качестве дополнительного примечания я обнаружил, что поставляемые Emscripten обертки C ++ для таких функций JavaScript, как рабочие, графика, аудио, http-запросы и т. Д., Хороши для начала, но имеют ограничения и не предоставляют всего, что технически возможно. Мне часто приходилось кататься самостоятельно, чтобы получить функционально необходимое. Хотя не по тем же причинам, мне также пришлось написать свой собственный API для рабочих.
Других решений пока нет …