Emscripten webworker - 自己的消息和依赖项
Emscripten webworker - Own messages and dependencies
我有一个 C++ 项目,我使用 emscripten 将其编译为 Javascript。但是,出于资源限制和交互性原因,这可行,我想 运行 在 webworker 中进行此操作。
但是,我的项目使用标准输入。我找到了一种方法,通过用一个函数覆盖 Module['stdin'] 来提供我自己的 stdin 实现,该函数在整个 stdin 的时间 returns 一个字符,并以 0 作为 EOF 结束。
这在页面内的脚本 运行s 时起作用,因为 html 文件中存在的模块对象与脚本共享。
当你 运行 作为网络工作者时,这个模块对象是不共享的。相反,消息传递确保 Module 的常规功能仍然有效。这不包括 'stdin'.
我通过修改输出 javascript:
解决了这个问题
- A:添加包含此标准输入规范的模块对象的实现。这个函数被修改为读取 webworker 的一个变量,就好像它是标准输入一样,并在每个字符的基础上提供它。
- B:更改 webworker 的 onmessage 以调用处理我自己的事件的附加函数。
- C:这个附加函数监听事件,当事件是stdin的内容时做出反应,通过设置我指定的stdin函数读取的变量。
- D:添加和删除此附加事件的 运行 依赖项,以防止 c++ 代码 运行ning 未指定标准输入。
在代码中:
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);}
显然,a & c 部分非常简单,因为它可以添加到 js 文件的开头(或接近开头),但是 b & d(添加你自己的依赖项并在loop) 要求您编辑内联代码。
由于我的项目非常大,找到必要的行进行编辑可能非常麻烦,在优化和模拟的 emscripten 代码中更是如此。
执行此操作的自动脚本以及解决方法本身可能会在新的 emscripten 版本上中断。
是否有更好、更合适的方法来实现相同的行为?
谢谢!
//编辑:
--separate-asm
标志非常有用,因为我必须编辑的文件现在只有几行长(以简化形式)。大大减轻了负担,但仍然不是一个正确的方法,所以我不愿意将其标记为已解决。
我知道实现你想要的唯一方法是不使用 Emscripten 提供的 worker API,而自己动手。所有的细节可能都超出了一个问题的范围,但在高层次上你需要...
使用您的处理代码编译工作模块,但不使用 BUILD_AS_WORKER 标志
在 UI 和 worker 端,您需要编写一些 JavaScript 代码来与 C++ 世界进行通信 in/out,使用以下方法之一http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html, that then directly calls the JavaScript worker API https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
中的技巧
在 Worker 端,您将能够控制 Module 对象,根据需要设置标准输入
作为旁注,我发现 Emscripten 提供的 JavaScript 功能的 C++ 包装器,例如 workers、图形、音频、http 请求等,一开始很好用,但是有局限性,不要暴露技术上可能的一切。我经常不得不自己动手来获得所需的功能。虽然不是出于同样的原因,我也不得不为工人写我自己的API。
我有一个 C++ 项目,我使用 emscripten 将其编译为 Javascript。但是,出于资源限制和交互性原因,这可行,我想 运行 在 webworker 中进行此操作。
但是,我的项目使用标准输入。我找到了一种方法,通过用一个函数覆盖 Module['stdin'] 来提供我自己的 stdin 实现,该函数在整个 stdin 的时间 returns 一个字符,并以 0 作为 EOF 结束。 这在页面内的脚本 运行s 时起作用,因为 html 文件中存在的模块对象与脚本共享。
当你 运行 作为网络工作者时,这个模块对象是不共享的。相反,消息传递确保 Module 的常规功能仍然有效。这不包括 'stdin'.
我通过修改输出 javascript:
解决了这个问题- A:添加包含此标准输入规范的模块对象的实现。这个函数被修改为读取 webworker 的一个变量,就好像它是标准输入一样,并在每个字符的基础上提供它。
- B:更改 webworker 的 onmessage 以调用处理我自己的事件的附加函数。
- C:这个附加函数监听事件,当事件是stdin的内容时做出反应,通过设置我指定的stdin函数读取的变量。
- D:添加和删除此附加事件的 运行 依赖项,以防止 c++ 代码 运行ning 未指定标准输入。
在代码中:
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);}
显然,a & c 部分非常简单,因为它可以添加到 js 文件的开头(或接近开头),但是 b & d(添加你自己的依赖项并在loop) 要求您编辑内联代码。 由于我的项目非常大,找到必要的行进行编辑可能非常麻烦,在优化和模拟的 emscripten 代码中更是如此。 执行此操作的自动脚本以及解决方法本身可能会在新的 emscripten 版本上中断。
是否有更好、更合适的方法来实现相同的行为?
谢谢!
//编辑:
--separate-asm
标志非常有用,因为我必须编辑的文件现在只有几行长(以简化形式)。大大减轻了负担,但仍然不是一个正确的方法,所以我不愿意将其标记为已解决。
我知道实现你想要的唯一方法是不使用 Emscripten 提供的 worker API,而自己动手。所有的细节可能都超出了一个问题的范围,但在高层次上你需要...
使用您的处理代码编译工作模块,但不使用 BUILD_AS_WORKER 标志
在 UI 和 worker 端,您需要编写一些 JavaScript 代码来与 C++ 世界进行通信 in/out,使用以下方法之一http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html, that then directly calls the JavaScript worker API https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
中的技巧在 Worker 端,您将能够控制 Module 对象,根据需要设置标准输入
作为旁注,我发现 Emscripten 提供的 JavaScript 功能的 C++ 包装器,例如 workers、图形、音频、http 请求等,一开始很好用,但是有局限性,不要暴露技术上可能的一切。我经常不得不自己动手来获得所需的功能。虽然不是出于同样的原因,我也不得不为工人写我自己的API。