我有一个C ++项目,我使用emscripten编译为Javascript。但是,由于资源限制和交互性原因,我希望在Webworker中运行它。
但是,我的项目使用stdin。我找到了一种方法来提供我自己的stdin实现,方法是用一个函数覆盖Module ['stdin'],该函数在总stdin时返回一个字符,并以0作为EOF关闭。 当脚本在页面内运行时,这是有效的,因为html文件中存在的Module对象与脚本共享。
当您作为webworker运行时,不会共享此模块对象。相反,消息传递确保Module的常规功能仍然有效。这不包括'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);}
显然,这是一个&amp; c部分非常简单,因为它可以在js文件的开始(或接近开始)添加,但是b&amp; d(添加自己的依赖项并在循环中获取自己的messagehandler)需要您内联编辑代码。
由于我的项目非常大,找到编辑所需的行可能非常麻烦,只有在优化和模仿的emscripten代码中才会如此。
执行此操作的自动脚本以及变通方法本身可能会破坏新的emscripten版本。
是否有更好,更正确的方法来达到相同的行为?
谢谢!
//编辑:
--separate-asm
标志非常有用,因为我必须编辑的文件现在只有几行(以模仿形式)。它大大减轻了负担,但仍然不是一种正确的方式,所以我不愿意将其标记为已解决。
答案 0 :(得分:1)
我知道实现您想要的唯一方法是不使用Emscripten提供的工作者API,并自行推送。所有细节都可能超出单个问题的范围,但在高水平,你需要......
使用处理代码编译worker模块,但不使用BUILD_AS_WORKER标志
在UI和工作端,你需要编写一些JavaScript代码,使用http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html中的一种技术在C ++世界中进行通信,然后直接调用JavaScript worker API https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
在此工作方面,您将能够控制Module对象,根据需要设置stdin
作为旁注,我发现Emscripten提供的用于JavaScript功能的C ++包装器,例如工作者,图形,音频,http请求等,一开始就很好,但是有局限性而且没有揭露技术上可行的一切。我经常不得不自己动手来获得功能所需。虽然不是出于同样的原因,但我还必须为工作人员编写自己的API。