Emscripten webworker-拥有消息和依赖关系

Emscripten webworker - Own messages and dependencies

本文关键字:依赖 关系 消息 webworker- 拥有 Emscripten      更新时间:2023-10-16

我有一个C++项目,我使用emscripten将其编译为Javascript。然而,由于资源限制和交互性的原因,我想在网络工作者中运行它。

但是,我的项目使用stdin。我找到了一种方法来提供我自己的stdin实现,方法是用一个函数覆盖Module[‘stin’],该函数在整个stdin中一次返回一个字符,并以0作为EOF结束。当脚本在页面内运行时,这是有效的,因为html文件中的Module对象与脚本共享。

但是,当您作为网络工作者运行时,此模块对象是不共享的。相反,消息传递可以确保Module的常规功能仍然有效。这不包括"stdin"。

我通过修改输出javascript:来解决这个问题

  • A: 添加包含此stdin规范的Module对象的实现。此函数被修改为读取webworker的变量,就好像它是stdin一样,并按每个字符提供它
  • B: 更改webworker的onmessage以调用一个处理我自己事件的附加函数
  • C: 这个附加函数通过设置我指定的stdin函数读取的变量来侦听事件,并在事件是stdin的内容时做出反应
  • D: 添加和删除此附加事件的运行依赖项,以防止在没有指定stdin的情况下运行c++代码

代码中:

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标志非常有用,因为我必须编辑的文件现在只有几行长(以模拟形式(。这大大减轻了负担,但这仍然不是一种合适的方式,所以我不愿意将其标记为已解决。

我所知道的实现您想要的目标的唯一方法是不使用Emscripten提供的worker API,而是自己滚动。所有的细节可能都超出了一个问题的范围,但在高水平上,你需要…

  • 使用处理代码编译辅助模块,但不使用BUILD_AS_worker标志

  • 在UI和worker端,您都需要编写一些JavaScript代码来在C++世界内外进行通信,使用http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html,然后直接调用JavaScript工作程序APIhttps://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers

    在Worker端,您将能够控制Module对象,根据设置stdin

顺便说一句,我发现Emscripten为JavaScript功能提供的C++包装器,如工人、图形、音频、http请求等,一开始很好,但有局限性,并且没有公开技术上可能的一切。我经常不得不自己滚动才能获得所需的功能。虽然不是出于同样的原因,但我也不得不为工人编写我自己的API。