Working with String in WebAssembly
In this blog I talked about 2 ways in which you can send string from javascript to C++ and vice-versa.
Introduction
In our last blog, we saw how to work with arrays in wasm. Now in this blog, you will learn how to work with string in wasm. So let's start.
Writing C++ code
In the code snippet below you can see a function named greet, which takes a character pointer as an argument and adds the desired greeting in this case Hello to it and returns the address of the greetingText.
#include<emscripten.h>
#include<iostream>
using namespace std;
extern "C"{
EMSCRIPTEN_KEEPALIVE
char* const greet(char* name){
std::cout<<name<<std::endl;
char greetingText[] = "Hello ";
strcat(greetingText,name);
return greetingText;
}
}
Here keyword EMSCRIPTEN_KEEPALIVE is used to tell the compiler to include the function greet in the final output code and extern "C" {} block is used to tell the compiler to preserve the naming of the function in the final output code.
Compiling the code
To compile the code we will use the command given below
em++ code.cpp -o function.js -sEXPORTED_FUNCTIONS=['_malloc'] -sEXPORTED_RUNTIME_METHODS=['ccall','UTF8ToString','lengthBytesUTF8','stringToUTF8'] -sMODULARIZE
Different keywords used in the command are explained below
em++ - triggers the emscripten.
code.cpp - the name of our c++ file
-o function.js - the name of our output file
-sEXPORTED_FUNCTIONS=['_malloc'] - tells the compiler to include malloc in the output code
-sEXPORTED_RUNTIME_METHODS=[...] - tells the compiler to include given methods in the output code
-sMODULARIZE - tells the compiler to wrap the modularised code so we get the module as a promise.
Now we have 2 output files - function.js which contains the necessary code to import and initialize the wasm code and function.wasm which contains the wasm code.
Writing JavaScript
So now as we have our wasm file ready we can write our script to interact with the wasm code.
So first of all create a basic HTML document and write the following lines of code in the head section.
<script src="./function.js"></script>
Now there are 2 ways in which we can send a string to a C++ function from JavaScript
Directly sending the string
Allocating memory and then sending the pointer.
I think the second one is the recommended one but both of them work.
1. Directly sending the array
In the case of direct sending our code will look like this
Module().then(mod => {
let name = "Rishab";
let num = mod.ccall("greet","number",['string'],[name]);
console.log(mod.UTF8ToString(num)); // Hello Rishab
});
In the snippet above we have a variable named name which is directly sent to the greet function using the ccall function which we have exported during the compilation. Then we used the UTF8ToString method also exported during the compilation which takes a character pointer as an argument and returns the string.
2. Allocating memory and then sending the pointer
In the case of sending a pointer our code snippet will look like this
Module().then(mod => {
let name = "Rishab";
let length = mod.lengthBytesUTF8(name);
let pointer = mod._malloc(length+1);
mod.stringToUTF8(name,pointer,length+1);
let num = mod.ccall("greet","number",['number'],[pointer]);
console.log(mod.UTF8ToString(num)); // Hello Rishab
})
Let's break down the snippet above and try to understand it.
First of all, we declared a variable named name.
Then we used the methods called lengthBytesUTF8 exported during the compilation to get the length of the variable in bits.
then used that length to allocate memory using malloc function which returns the address of the allocated memory.
then we used the stringToUTF8 method to assign the name variable in that memory.
Finally, we called the greet function using ccall.
Lastly, we retrieved the string using the UTF8ToString method.
Conclusion
So in this blog we learned 2 ways in which we can send string from javascript to C++. If you like this blog press like button and if you find any mistake or have some suggestion comment below👇.