Build your first webassembly project

Hey makkals, This post is a part of a multi-part series on WebAssembly. Check out other parts of the series here Have you ever heard about WebAssembly and thought, "That sounds cool, but it's probably too complex for me"? Well, today you're going to build a simple WebAssembly project from scratch. Let me set the right expectations. We are going to build a very simple project which generates random hexadecimal color code. Think of it as the “Hello, World!” of WebAssembly with a splash of color. By the end, you'll learn how to write simple WebAssembly code, compile it, and use it with JavaScript to generate random colors right in your browser. Setup WebAssembly In this blog post series, we will be using C and C++ for examples. So we will be using a tool called Emscripten to compile our C / C++ code to WASM. However, you can use any supported language with the respective compiling tools. Setting up Emscripten is straightforward. Just follow this page - https://emscripten.org/docs/getting_started/downloads.html If you're using macOS, you can simply use homebrew to install it, brew install emscripten If you're using linux, follow this post - https://marcoselvatici.github.io/WASM_tutorial/#install_emscripten After setting up Emscripten, you should be able to run the following command in your terminal, emcc -v Simple addition Before implementing a random hex code generator, let's build something simple first to understand the WASM workflow. Let's build an application that just adds 2 numbers. We will first build the application in JavaScript and then it into WASM later. Create a file named index.html and paste the following code, Add function addNumbers() { const num1 = parseInt(document.getElementById('num1').value); const num2 = parseInt(document.getElementById('num2').value); const result = addTwoNumbers(num1, num2); document.getElementById('result').textContent = `Result: ${result}`; } function addTwoNumbers(num1, num2) { const result = num1 + num2; return result; } The code is self-explanatory. On clicking the button, we get 2 numbers from the input fields and pass it to addTwoNumbers function. And the function returns a number which we display inside a paragraph. Now let's move the addTwoNumbers function to C language. Create a file named add.c and write the following piece, // add.c int addTwoNumbers(int num1, int num2) { return num1 + num2; } Now, let's compile the C code to WASM, emcc add.c -o add.js -s EXPORTED_FUNCTIONS="['_addTwoNumbers']" -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']" Let's breakdown what this command does, emcc add.c -o add.js - Tells the Emscripten compiler to compile the C code from add.c to JavaScript in a file named add.js -s EXPORTED_FUNCTIONS="['_addTwoNumbers']" - Tells the compiler to export the addTwoNumbers function so it can be used in JavaScript. The underscore (_) is part of the command, not part of the function name. -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']" - Tells the compiler to export additional runtime functions - cwrap and ccall are the functions that we use to wrap a C function and call it from JavaScript respectively. After successful compilation, 2 new files would be generated - add.wasm and add.js. Here, add.wasm is the actual WASM binary file that the browser will run. add.js is just a glue-code that lets us use the functions defined in the C language seamlessly. And change the HTML file as follows, Add // Wrap the function provided by C const addTwoNumbers = Module.cwrap("addTwoNumbers", "number", ["number", "number"]); function addNumbers() { const num1 = parseInt(document.getElementById('num1').value); const num2 = parseInt(document.getElementById('num2').value); // Calling the wrapped function const result = addTwoNumbers(num1, num2); document.getElementById('result').textContent = `Result: ${result}`; } Here, Module.cwrap is used to wrap the C function, so that we can use it as a normal JavaScript function. cwrap takes three parameters, function name - addTwoNumbers return type - number types of parameters - [number, number] Run the application from a local server. If you don't have a local server installed in your machine, try any one of the following. If you have Python 3 installed, try these, python -m http.server python3 -m http.server Or, if you have NodeJS installed, try the following, npm i -g live-server and run the following command in the directory which contains the all the files that we have created now, live-server If everything went well, you will be able to see 2 input fields. Try entering 2 numbers and click the button to see the result. Here, all the DOM manipulations such as event l

Jan 21, 2025 - 04:46
 0
Build your first webassembly project

Hey makkals,

This post is a part of a multi-part series on WebAssembly. Check out other parts of the series here

Have you ever heard about WebAssembly and thought, "That sounds cool, but it's probably too complex for me"?

Well, today you're going to build a simple WebAssembly project from scratch. Let me set the right expectations. We are going to build a very simple project which generates random hexadecimal color code.

Think of it as the “Hello, World!” of WebAssembly with a splash of color. By the end, you'll learn how to write simple WebAssembly code, compile it, and use it with JavaScript to generate random colors right in your browser.

Setup WebAssembly

In this blog post series, we will be using C and C++ for examples. So we will be using a tool called Emscripten to compile our C / C++ code to WASM. However, you can use any supported language with the respective compiling tools.

Setting up Emscripten is straightforward. Just follow this page - https://emscripten.org/docs/getting_started/downloads.html

If you're using macOS, you can simply use homebrew to install it,

brew install emscripten

If you're using linux, follow this post - https://marcoselvatici.github.io/WASM_tutorial/#install_emscripten

After setting up Emscripten, you should be able to run the following command in your terminal,

emcc -v

Simple addition

Before implementing a random hex code generator, let's build something simple first to understand the WASM workflow. Let's build an application that just adds 2 numbers.

We will first build the application in JavaScript and then it into WASM later. Create a file named index.html and paste the following code,


   type="number" id="num1" placeholder="Enter first number">
   type="number" id="num2" placeholder="Enter second number">
   onclick="addNumbers()">Add
   id="result">

  

The code is self-explanatory. On clicking the button, we get 2 numbers from the input fields and pass it to addTwoNumbers function. And the function returns a number which we display inside a paragraph.

Now let's move the addTwoNumbers function to C language. Create a file named add.c and write the following piece,

// add.c
int addTwoNumbers(int num1, int num2) {
    return num1 + num2;
}

Now, let's compile the C code to WASM,

emcc add.c -o add.js -s EXPORTED_FUNCTIONS="['_addTwoNumbers']" -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']"

Let's breakdown what this command does,

  • emcc add.c -o add.js - Tells the Emscripten compiler to compile the C code from add.c to JavaScript in a file named add.js
  • -s EXPORTED_FUNCTIONS="['_addTwoNumbers']" - Tells the compiler to export the addTwoNumbers function so it can be used in JavaScript. The underscore (_) is part of the command, not part of the function name.
  • -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']" - Tells the compiler to export additional runtime functions - cwrap and ccall are the functions that we use to wrap a C function and call it from JavaScript respectively.

After successful compilation, 2 new files would be generated - add.wasm and add.js. Here,

  • add.wasm is the actual WASM binary file that the browser will run.
  • add.js is just a glue-code that lets us use the functions defined in the C language seamlessly.

And change the HTML file as follows,


     type="number" id="num1" placeholder="Enter first number">
     type="number" id="num2" placeholder="Enter second number">
     onclick="addNumbers()">Add
     id="result">

    
    

    
  

Here, Module.cwrap is used to wrap the C function, so that we can use it as a normal JavaScript function.

cwrap takes three parameters,

  • function name - addTwoNumbers
  • return type - number
  • types of parameters - [number, number]

Run the application from a local server. If you don't have a local server installed in your machine, try any one of the following.

If you have Python 3 installed, try these,

python -m http.server
python3 -m http.server

Or, if you have NodeJS installed, try the following,

npm i -g live-server

and run the following command in the directory which contains the all the files that we have created now,

live-server

If everything went well, you will be able to see 2 input fields. Try entering 2 numbers and click the button to see the result.

Demo of adding 2 numbers using WebAssembly

Here, all the DOM manipulations such as event listeners, getting value from inputs, displaying result are done by JavaScript. Whereas, the addition is done by WASM which was written in C language.

You can find the full code for this project - here

Now let's start working on our actual project - random hexadecimal color generator

What is hexadecimal?

Before building our project, let's understand what is hexadecimal and how it can be represented as colors.

Hexadecimal is a number system with base 16. It means, the number system contains 16 symbols to represent values. The possible hexadecimal symbols are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, followed by A, B, C, D, E, F.

Here, A = 10, B = 11 and so on..

Hexadecimal representation

We can use hex code to represent colors with six digits. For example, #FF5733 or #42A5F5

To understand more about colors and their representation, read - Understanding Hexadecimal Colors.

Random color generator

Let's write our C code first. Create a file named random_color.c

We need to use two libraries: stdlib.h and time.h,

// random_color.c

#include 
#include 

We define the generateRandomHexColor function, which returns a character pointer.

char* generateRandomHexColor() {
    // ...
}

Let's define necessary variable we need, and initiate random seed

char* generateRandomHexColor() {
    static char color[8]; // Store the color as a string (e.g., "#A3B2C7")

    srand(time(NULL));

    color[0] = '#';
}

We can use the rand function to generate a random number between 0 and 255. Then we need to convert it into a hexadecimal digit (i.e., 0 - 9 and A - F).

Let's first write an util function that converts an integer into a valid hex value,

char* intToHex(int num) {
    static char hexStr[3]; // Store the hex string (2 characters + null terminator)
    const char hexDigits[] = "0123456789ABCDEF";

    hexStr[0] = hexDigits[(num >> 4) & 0xF]; // High nibble
    hexStr[1] = hexDigits[num & 0xF];         // Low nibble
    hexStr[2] = '\0';                         // Null terminator

    return hexStr;
}

char* generateRandomHexColor() {
    // ...
}

Now we can use this intToHex function to convert our random numbers into hex code. The final code is,

// random_color.c

#include 
#include 

char* intToHex(int num) {
    static char hexStr[3]; // Store the hex string (2 characters + null terminator)
    const char hexDigits[] = "0123456789ABCDEF";

    hexStr[0] = hexDigits[(num >> 4) & 0xF]; // High nibble
    hexStr[1] = hexDigits[num & 0xF];         // Low nibble
    hexStr[2] = '\0';                         // Null terminator

    return hexStr;
}

char* generateRandomHexColor() {
    static char color[8]; // Store the color as a string (e.g., "#A3B2C7")

    srand(time(NULL));

    color[0] = '#';

    char* r = intToHex(rand() % 256);
    color[1] = r[0];
    color[2] = r[1];

    char* g = intToHex(rand() % 256);
    color[3] = g[0];
    color[4] = g[1];

    char* b = intToHex(rand() % 256);
    color[5] = b[0];
    color[6] = b[1];

    color[7] = '\0'; // Null terminator to make it a valid string

    return color;
}

Now let's compile it to WASM,

emcc random_color.c -o random_color.js -s EXPORTED_FUNCTIONS="['_generateRandomHexColor']" -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap', 'UTF8ToString']"

And let's prepare a HTML file to use this function,


  

Random Background Color

onclick="changeBackgroundColor()">Generate Random Color

If everything goes well, you should be able to click a button that changes the background color of the page.

Demo of random hex color generator using WebAssembly

It's totally okay if don't understand how we get the color from pointer and how C's pointers are accessible via JavaScript. We will see more about WebAssembly architecture and memory in the upcoming posts.

You can find the full code for this project - here

Conclusion

In this post, we've taken our first steps in WebAssembly by writing simple C code, compiling it into WASM using Emscripten, and integrating it with JavaScript to build a functional random color generator. While this project is just the beginning, it shows the power and flexibility of WebAssembly in bringing high-performance code to the web.

With WebAssembly, you can unlock new possibilities for building faster, more efficient web applications. In future posts, we'll explore more advanced use cases, like image processing, to further understand how WebAssembly can enhance performance and extend JavaScript's capabilities.

Stay tuned for more hands-on examples and deeper dives into WebAssembly

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow