preface
We know that the WASM and HOST environment (Browser) share space through linear memory, so essentially exchanging data is storing and retrieving data in this shared memory and how it is encoded.
How does the corresponding WASM product store data in memory? For example, in the following example, the data is directly addressed in memory
Different data structures (Array, Object, Struct) have their own memory space definitions, so I only Case strings
String type
Wasm to js
Index. c: defines the get_str_from_wasm method, which returns a string pointer
// wasm string pointer
char * get_str_from_wasm(void) {
return (char *)"Hello, From WASM";
}
Copy the code
Compile the Makefile:
main:
emcc \
index.c \
-s ERROR_ON_UNDEFINED_SYMBOLS=0 \
-s EXPORTED_FUNCTIONS="[_malloc,_free,_get_str_from_js]" \
--no-entry \
-o \
./index.wasm
clean:
rm -rfv *.wasm
Copy the code
Index. HTML: load WASM and fetch memory data by 1byte(8Bit)
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Shared</title>
</head>
<script type="text/javascript">
(async function () {
function AsciiToString(ptr, heapu8) {
let str = ' ';
while (1) {
let ch = heapu8[ptr++];
if(! ch)return str;
str += String.fromCharCode(ch); }}const resp = await fetch(`./index.wasm? t=The ${Date.now()}`);
const bytes = await resp.arrayBuffer();
const { instance } = await WebAssembly.instantiate(bytes, {
env: {},});// Structured data
const HEAP8 = new Int8Array(instance.exports.memory.buffer);
// get string from wasm
const wasm_str_ptr = instance.exports.get_str_from_wasm();
const wasm_str = AsciiToString(wasm_str_ptr, HEAP8);
console.log(wasm_str); //Hello, From WASM
})().catch(err= > console.error(err));
</script>
</body>
</html>
Copy the code
I only encode and decode data in ASCII format. In fact, if utF-8 data is involved, I need to use Int32Array to fetch and decode data.
Js to wasm
Index. c: Define set_str_from_js to set the string and get_str_from_js to set the string pointer
char * js_str;
// set string pointer
void set_str_from_js(char * str) {
js_str = str;
}
// return string pointer
char * get_str_from_js(a) {
return js_str;
}
Copy the code
Makefile
main:
emcc \
index.c \
-s ERROR_ON_UNDEFINED_SYMBOLS=0 \
-s EXPORTED_FUNCTIONS="[_malloc,_free,_get_str_from_wasm,_set_str_from_js]" \
--no-entry \
-o \
./index.wasm
clean:
rm -rfv *.wasm
Copy the code
Because index.html
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Shared</title>
</head>
<script type="text/javascript">
(async function () {
function AsciiToString(ptr, heapu8) {
let str = ' ';
while (1) {
let ch = heapu8[ptr++];
if(! ch)return str;
str += String.fromCharCode(ch); }}const resp = await fetch(`./index.wasm? t=The ${Date.now()}`);
const bytes = await resp.arrayBuffer();
const { instance } = await WebAssembly.instantiate(bytes, {
env: {},});const str = "Hello, From JS";
const str_ptr = instance.exports.malloc(str.length);
const HEAP8 = new Int8Array(instance.exports.memory.buffer);
// 1 byte Set the value in the memory in the format of 1 byte and modify the WASM memory data directly
str.split(' ').forEach((char, index) = > {
HEAP8[(str_ptr + index) >> 0] = char.charCodeAt(0);
});
// Pass the pointer
instance.exports.set_str_from_js(str_ptr);
/ / get the value
const str_ptr_from_wasm = instance.exports.get_str_from_js();
const str_from_wasm = AsciiToString(str_ptr_from_wasm, HEAP8);
console.log(str_from_wasm); // "Hello, From JS"
})().catch(err= > console.error(err));
</script>
</body>
</html>
Copy the code
Write data to the corresponding memory space and pass pointer to the WASM method.
Other types of data
Other high-level types of data, which depend on the corresponding storage structure, can be passed in the higher-order wrap form, similar in nature to String.