如何从本地JavaScript有效地将参数列表发送到Emscripten Web Worker?我的数据(参数集)是Float32Array
,UInt16Array
,int
等大型数组的不均匀组合。下面的示例有效,但是我不能使用列表,字典或任何其他方式来创建TypedArrays元组与int混合。当前,除非输入是一个TypedArray,否则它将转换为几个字节。例如,以下行将发送三个单字节,每个参数一个。
test_data_worker([b8verts, 150000, b8faces]); // doesn't work
实际上,我的问题是如何将元组编码为C结构。我可以使用诸如struct.js之类的库,但是它们的效率很低(需要转换,并且参数不可转让)。 Emscripten对于这种情况有什么解决方案。请注意,我的特殊要求是我希望我的JavaScript直接
postMessage()
到Emscripten编译的C ++函数中,而不必由前端的发送方C ++程序或辅助方的接收方JavaScript代码所介导。
<html> <script> 'use strict'; var worker = new Worker('./emworker.compiled.js'); var api_info = { test: { funcName: "worker_function", callbackId: 3, }, }; function test_data_worker(arguments_data_buffer) { // The protocol used by Emscripten worker.postMessage( { funcName: api_info.test.funcName, callbackId: api_info.test.callbackId, data: arguments_data_buffer, // 'finalResponse': false, } // , [arguments_data_buffer] //uncommet for transferable ); } function demo_request() { var verts = new Float32Array([3.141592651234567890123456780,1,2, 3,4,5, 6,7,8, 9,0.5,1.5]); var faces = new Uint16Array([0,1,2, 1,2,3, 0,1,3, 0,2,3]); var b8verts=new Uint8Array(verts.buffer); var b8faces=new Uint8Array(faces.buffer); test_data_worker(b8verts); // b8verts.buffer to make it transferrable // Desired: //test_data_worker([b8verts, b8faces]); // Doesnt work. sends two bytes instead //test_data_worker([b8verts, 60, b8faces]); // doesnt work //test_data_worker({verts:b8verts, d:60, faces:b8faces}); // doesnt work } worker.addEventListener('message', function(event) { // event.data is {callbackId: -1, finalResponse: true, data: 0} switch (event.data.callbackId) { case api_info.test.callbackId: //api_revlookup.: // console.log("Result sent back from web worker", event.data); // Reinterpret data var uint8Arr = event.data.data; var returned_message = String.fromCharCode.apply(null, uint8Arr) console.log(returned_message); break; default: console.error("Unrecognised message sent back."); } }, false); demo_request(); console.log("request() sent."); </script> </html>
和工人的C ++代码类似
#include <iostream> #include <emscripten/emscripten.h> extern "C" { int worker_function(void* data, int size); } std::string hexcode(unsigned char byte) { const static char codes[] = "0123456789abcdef_"; std::string result = codes[(byte/16) % 16] + ( codes[byte % 16] + std::string()); return std::string(result = codes[(byte/16) % 16] + ( codes[byte % 16] + std::string())); } int worker_function(void* data, int size) { { std::cout << "As bytes: "; size_t i = 0 ; char* char_data = (char*)data; for (; i < size; ++i) { std::cout << hexcode((char_data)[i]) << " "; } std::cout << std::endl; } { std::cout << "As float: "; float* typed_data = (float*)data; size_t typed_size = (size + sizeof(float)-1) / sizeof(float); for (size_t i = 0; i < typed_size; ++i) { std::cout << typed_data[i] << " "; } std::cout << std::endl; } std::string result = std::string("I received ") + std::to_string(size) + " bytes."; char* resstr = (char*)result.c_str(); emscripten_worker_respond(resstr, result.size()); // not needed really return 314; // ignored } void worker_function2(float*verts, int numverts, int*faces, int numfaces) { // } int main(){return 0;}
使用Emscripten通过以下方式编译:
em++ -s EXPORTED_FUNCTIONS="['_main', '_worker_function' , '_worker_function2' ]" \ -s NO_EXIT_RUNTIME=1 \ -s DEMANGLE_SUPPORT=1 \ -s BUILD_AS_WORKER=1 -DBUILD_AS_WORKER \ -pedantic -std=c++14 \ emworker.cpp \ -o ./emworker.compiled.js
我的网络工作者上的API需要发送和接收多种类型的元组,即它将具有如下所示的输入和输出:
typedef struct vf_pair {
std::vector<float> verts, // or a pair<float*,int>
std::vector<int> faces
} mesh_geometry;
int query_shape(char* reduce_operator, char* shape_spec_json, float* points, int point_count);
struct vf_pair get_latest_shape(int obj_id);
struct vf_pair meshify(char* implicit_object);
如何从本地JavaScript有效地将参数列表发送到Emscripten Web Worker?我的数据(参数集)是Float32Array大数组的不均匀组合,...
您可以找到我在以下回购中使用的模式。这是有效的。它与Web Workers来回交换大型数组和原始类型值: