Webassembly返回c ++ uint8_t数组并将其传递给javascript Uint8Array

问题描述 投票:0回答:1

将c ++的字节数组返回到webassembly,然后将该字节数组传递给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。

在互联网上,我见过两种方式:

1)首先是将第三个参数传递给函数ThatExtendsTheOriginalStringsAndReturnsAnotherString方法,即另一个已经存在于Module.HEAPU8中的整数,然后让c ++对其进行初始化那么我将不得不从Java脚本中读取它

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);

第一个整数地址是指向新创建的字节数组的指针,第二个整数地址是该数组的长度。我对上述2种方法中的任何一种都没有特别的发现,因为对于应该更容易完成的事情而言,似乎有很多工作要做。

有更好的方法吗?

从CMAKE编译wasm的方式

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']'   " )

2020年1月28日增加

为了从JavaScript读取最终的字符串,我使用了此

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

同样在这里问题是长度90,因为我需要在开始读回字符串之前就知道长度

最佳做法是将字节数组从c ++返回到Webassembly,然后将该字节数组传递给Javascript Uint8Array。目前,我有一个c ++方法,该方法将字符串作为参数...

javascript c++ c++17 webassembly emscripten
1个回答
0
投票

问题是长度90,因为我需要在开始读回字符串之前就知道长度

© www.soinside.com 2019 - 2024. All rights reserved.