Webassembly возвращает массив c ++ uint8_t и передает его javascript Uint8Array - PullRequest
0 голосов
/ 27 января 2020

Как лучше всего возвращать массив байтов из c ++ в веб-сборку и затем передавать этот байтовый массив в Javascript Uint8Array

В настоящее время у меня есть метод c ++, который принимает строку в качестве параметра

var theString = 'The quick brown fox jumps over the lazy dog';
const encoder = new TextEncoder();
const input_array = encoder.encode(theString);
var len = input_array.length;
var bytes_per_element = input_array.BYTES_PER_ELEMENT; 

var input_ptr  = Module._malloc(len * bytes_per_element );

Module.HEAPU8.set(input_array, input_ptr / bytes_per_element); // write WASM memory calling the set method for the Uint8Array
var extendedStringPtr = Module._functionThatExtendsTheOriginalStringsAndReturnsAnotherString(input_ptr, len );

var extendedStringLength = 90
var output_array = new Uint8Array(Module.HEAPU8.buffer, extendedStringPtr, extendedStringLength);
var newstring = new TextDecoder('utf8').decode(output_array);
console.log(newstring);
Module._free(input_ptr);

и часть c ++

  char* EMSCRIPTEN_KEEPALIVE functionThatExtendsTheOriginalStringsAndReturnsAnotherString(
        char* str, int length   )
 {

    string s1(str, length);
    std::cout << "original string received from JavaScript is :" <<  s1 << std::endl;

    string s2 = ", then Godzilla jumps out and party is over! :)";
    string s3 = s1 + s2;

    std::cout << "Final string " <<  s3 << std::endl;
    std::cout << "Final string  length " <<  s3.length() << std::endl;

    // create a character buffer to return
     char * char_array = new char [s3.length()+1];
     strcpy (char_array, s3.c_str());

    // create a char pointer and return it
     char* arrayPtr = &char_array[0];
     return arrayPtr;

 }

Теперь проблема здесь в "extendedStringLength", т.е. у меня его нет в данный конкретный момент времени. Как я могу передать его наиболее удобным способом от C ++ до javascript.

На inte rnet я видел 2 способа:

1) первый - передать в метод functionThatExtendsTheOriginalStringsAndReturnsAnotherString третий параметр, т.е. другое целое число, которое уже находится в Module.HEAPU8 и пусть c ++ initializ ie, тогда мне нужно будет прочитать, что из java script

2) создать структуру фиксированной длины, такую ​​как

struct MyControllStruct {

uint32_t* arrayBufferPtr;
uint32_t arrayBufferLength;
};

https://dev.to/azure/passing-structured-data-from-c-to-javascript-in-web-assembly-1i0p И так как я знаю, что эта структура имеет длину ровно 8 байт, то есть 4 + 4, мне придется читать это каждый раз, как это в JavaScript

var MyControllStruct =  new Int32Array(Module.HEAP32.buffer, output_ptr, 8);

, первый целочисленный адрес - указатель на Вновь созданный байтовый массив, а второй - длина этого массива. Я не особо разбираюсь ни в одном из вышеперечисленных пунктов, так как кажется, что для чего-то, что должно быть легче сделать, требуется много работы.

Есть ли лучший способ сделать это?

Способ компиляции wasm из CMAKE

set_target_properties(wasmExec PROPERTIES LINK_FLAGS "-std=c++17 -s WASM=1 -s TOTAL_MEMORY=512MB  -s NO_EXIT_RUNTIME=1  -s VERBOSE=1  --pre-js /src/wasm/preModule.js -s DEMANGLE_SUPPORT=1 -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s EXTRA_EXPORTED_RUNTIME_METHODS='['cwrap', 'getValue', 'setValue']'   " )

Дополнение 28 января 2020

В порядке чтобы прочитать последнюю строку обратно из Javascript Я снова использую эту

var output_array = new Uint8Array(Module.HEAPU8.buffer, extendedStringPtr, 90);
var newstring = new TextDecoder('utf8').decode(output_array);
console.log(newstring);

, здесь проблема в длине 90, так как мне нужно знать ее, прежде чем я начну читать строку обратно

...