What is WebAssembly (Wasm)?
WebAssembly, or Wasm, is a way that allows us to run compiled code from other languages alongside JavaScript in the browser. According to MDN (Mozilla Developer Network), it is:
WebAssembly is a type of code that can be run in modern web browsers — it is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++, C# and Rust with a compilation target so that they can run on the web. It is also designed to run alongside JavaScript, allowing both to work together.
Here, I won't delve into the significance of WebAssembly (Wasm) or the scenarios where it's beneficial. Numerous blog posts about Wasm are available on the web that you can explore and read. Instead, I'll be providing a basic introduction, scratching the surface, and guiding you through the initial steps to start using it.
Compiler installation & First example
As an example, I am trying to simply run a code that is written in C in the browser. For this purpose, we need a compiler to compile our code to the wasm file. A compiler like gcc, which is a C compiler, is used. The Emscripten compiler.
Starting by cloning the repository like so:
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
emsdk install latest
After the installation is finished and the source folder is added to our system environment (making access easier),
we should activate the SDK in our working repository. Let's assume our repository is located at src/wasm
.
cd ./src/wasm
emsdk activate latest
Then we can verify it by using the emcc -v
command.
Everything is ready now, and we can write our first code to be compiled. Let's start with the hello world example:
#include <stdio.h>
int main(){
printf("Hello world!\n");
return 0;
}
Then by the command emcc hello_world.c
, we can compile the code.
If there are any errors in the code, they will be displayed; otherwise, it will be compiled successfully.
![The hello world example written in C](/_next/image?url=%2Fimages%2Fcontent%2Fwasm1%2Fexample1.png&w=3840&q=75)
After compiling the code successfully, two files will be generated as follows:
a.out.js (A wrapper that calls the wasm file)
a.out.wasm (The compiled file in wasm format)
Having these files, we can use the wrapper JavaScript file in our code. As an example, let's call it in a simple HTML file and look for the output, as shown in the code below:
<html lang="en">
<head>
<title>WASM Example</title>
</head>
<body>
<h1>Check the console log!</h1>
<script src="./a.out.js"></script>
</body>
</html>
Open the console and check the output there.
Tada! As you can see, we are getting the 'Hello world!' from code written in C in the browser. Isn't it cool 😎?
![The output example](/_next/image?url=%2Fimages%2Fcontent%2Fwasm1%2Flog.png&w=3840&q=75)
As you can see above, we get the output in the console. Actually, we can also call this script file with node as well, like this:
node a.out.js
// Hello world!
Additionally, by calling this wrapper the wasm file will be loaded in the browser and we can observe it in the network tab.
![Wasm file in the network tab](/_next/image?url=%2Fimages%2Fcontent%2Fwasm1%2Fwasm.png&w=3840&q=75)
Note: By using the -o
switch, we can define the output file name when compiling the code.
This command will generate two files with the name we defined.
emcc hello_world.c -o output.js
output.js
output.wasm
Export functions
Now, the very first question that comes to mind is how can we call the C function in our JavaScript file.
Let's write a new code for our example. This time, we'll implement the addNumber function.
However, in order to use it in our JavaScript file, we need some extra code specific to Emscripten.
First, we should include the header file emscripten.h
and add the line number 3 before any functions that we want to export.
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int addNumber(int a, int b){
return a + b;
}
Now, we can use the following command to compile our code:
emcc math.c -o math.js -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=ccall,cwrap
Here we specify the exported methods as ccall and cwrap.
Now, we can leverage those methods to access the addNumber function.
Firstly, I am going to show you how we can use the ccall. But before that,
we should know that the wrapper file that we get from the compiler exports the object called Module
,
and it has those methods that we want.
Here we are defining two inputs to simulate the add number functions;
<html lang="en">
<head>
<title>Welcome to wasm!</title>
<script src="./math.js"></script>
</head>
<body>
<input id="a" type="number" />
<input id="b" type="number" />
<button onclick="handleAddNumber()">Add</button>
<div id="result">--</div>
<script>
function handleAddNumber() {
const a = document.getElementById('a').value;
const b = document.getElementById('b').value;
const result = Module.ccall(
'addNumber', // the name of the exported functions
'number', // type of the returned value
['number', 'number'], // type of the arguments
[a, b] // arguments
);
document.getElementById('result').innerText = `${a} + ${b}=${result}`;
}
</script>
</body>
</html>
This is the result obtained from the above file.
![Wasm file in the network tab](/_next/image?url=%2Fimages%2Fcontent%2Fwasm1%2FaddNumber.gif&w=3840&q=75)
But what if we want to use the addNumber function in a couple of places? Should we define the ccall properties every time and get the result? Fortunately not. This is where cwrap can solve the issue for us. Let's refactor the code using cwrap.
<script>
const addNumbers = Module.cwrap('addNumber', 'number', ['number', 'number']);
function handleAddNumber() {
const a = document.getElementById('a').value;
const b = document.getElementById('b').value;
const result = addNumbers(a, b);
document.getElementById('result').innerText = `${a} + ${b}=${result}`;
}
</script>
As you can see, it is a more easier and better way to use functions in our code, and the result will be the same as before.
That's it for this part, and in the next part, we will cover more topics in the world of WebAssembly, delving deeper into its functionalities and applications.