Как я могу эффективно отправить список аргументов в Emscripten Web Worker из собственного JavaScript?
Мои данные (набор аргументов) представляют собой неоднородную комбинацию больших массивов Float32Array
, UInt16Array
, int
и т. д. Пример ниже работает, но я не могу использовать список, словарь или любой другой способ создания кортежа TypedArrays, смешанного с int. В настоящее время, если входные данные не являются одним TypedArray, он преобразуется в несколько байтов. Например, следующая строка отправит три отдельных байта, по одному для каждого аргумента.
test_data_worker([b8verts, 150000, b8faces]); // doesn't work
Мой вопрос на самом деле, как закодировать кортеж в структуру C. Я могу использовать библиотеки, такие как struct.js, но они будут неэффективными (необходимо преобразование, и аргументы не будут передаваться). Какое решение имеет Emscripten для такого случая. Обратите внимание, что мое особое требование заключается в том, чтобы 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);
Задача ещё не решена.
Других решений пока нет …