WebAssembly - Working with C++

Hello, aspiring programmers! I'm thrilled to be your guide on this exciting journey into the world of WebAssembly and C++. As someone who's been teaching computer science for over a decade, I can assure you that while this topic might seem daunting at first, we'll break it down into bite-sized pieces that even complete beginners can digest. So, let's roll up our sleeves and dive in!

WebAssembly - Working with C++

What is WebAssembly?

Before we jump into the code, let's understand what WebAssembly is all about. Imagine you're trying to speak to someone who doesn't know your language. You'd need a translator, right? Well, WebAssembly is like that translator for your web browser. It allows programs written in languages like C++ to run in web browsers at near-native speed. Cool, huh?

Why C++ with WebAssembly?

You might wonder, "Why C++?" Well, C++ is like the Swiss Army knife of programming languages - it's powerful, flexible, and has been around for ages. When combined with WebAssembly, it allows us to bring high-performance applications to the web. It's like turbocharging your website!

Setting Up Our Environment

Before we write our first line of code, we need to set up our workspace. Don't worry, I'll walk you through it step by step:

  1. Install Emscripten: This is our magic wand that turns C++ into WebAssembly.
  2. Set up a text editor: I recommend Visual Studio Code, but any text editor will do.
  3. Open a terminal: We'll use this to compile our code.

Our First WebAssembly Program

Let's start with a simple "Hello, World!" program. Here's the code:

#include <emscripten/emscripten.h>
#include <stdio.h>

extern "C" {
    EMSCRIPTEN_KEEPALIVE
    void sayHello() {
        printf("Hello, WebAssembly World!\n");
    }
}

Now, let's break this down:

  • #include <emscripten/emscripten.h>: This line includes the Emscripten header file, giving us access to WebAssembly-related functions.
  • extern "C": This tells the compiler to use C-style naming for our functions.
  • EMSCRIPTEN_KEEPALIVE: This is like putting a "Do Not Erase" sign on our function, ensuring it's available to JavaScript.
  • void sayHello(): This is our function that prints the greeting.

Compiling Our Code

Time to wave our magic wand! In your terminal, run:

emcc hello.cpp -o hello.html -s NO_EXIT_RUNTIME=1 -s "EXPORTED_RUNTIME_METHODS=['ccall']"

This command might look like a spell from Harry Potter, but let me explain:

  • emcc: This is our compiler.
  • hello.cpp: Our source file.
  • -o hello.html: This creates an HTML file we can open in a browser.
  • The rest are special flags to make our WebAssembly play nice with JavaScript.

Running Our WebAssembly

Open the generated hello.html in your browser, open the console, and type:

Module.ccall('sayHello', null, null, null);

If you see "Hello, WebAssembly World!" in the console, congratulations! You've just run C++ in your browser!

A More Complex Example: Fibonacci Calculator

Now that we've got our feet wet, let's try something a bit more challenging - a Fibonacci number calculator.

#include <emscripten/emscripten.h>

extern "C" {
    EMSCRIPTEN_KEEPALIVE
    int fibonacci(int n) {
        if (n <= 1) return n;
        return fibonacci(n-1) + fibonacci(n-2);
    }
}

This function calculates the nth Fibonacci number recursively. It's not the most efficient method, but it's great for demonstration!

Compile it the same way as before, then call it from JavaScript like this:

console.log(Module.ccall('fibonacci', 'number', ['number'], [10]));

This should print the 10th Fibonacci number (which is 55, by the way).

Working with Arrays

Let's level up and work with arrays. Here's a function that calculates the sum of an array:

#include <emscripten/emscripten.h>

extern "C" {
    EMSCRIPTEN_KEEPALIVE
    int sumArray(int* arr, int size) {
        int sum = 0;
        for (int i = 0; i < size; i++) {
            sum += arr[i];
        }
        return sum;
    }
}

To use this from JavaScript, we need to do a bit more work:

let arr = new Int32Array([1, 2, 3, 4, 5]);
let buffer = Module._malloc(arr.length * arr.BYTES_PER_ELEMENT);
Module.HEAP32.set(arr, buffer >> 2);
let sum = Module.ccall('sumArray', 'number', ['number', 'number'], [buffer, arr.length]);
Module._free(buffer);
console.log(sum);  // Should print 15

This might look complicated, but we're essentially:

  1. Creating an array in JavaScript
  2. Allocating memory in WebAssembly's heap
  3. Copying our array to that memory
  4. Calling our function
  5. Freeing the allocated memory

Conclusion

Congratulations! You've taken your first steps into the world of WebAssembly with C++. We've covered a lot of ground, from basic "Hello, World!" to working with arrays. Remember, learning to code is like learning a new language - it takes practice and patience. Don't be discouraged if you don't understand everything right away. Keep experimenting, keep coding, and most importantly, keep having fun!

Here's a table summarizing the main methods we've used:

Method Description
emcc Emscripten compiler command
EMSCRIPTEN_KEEPALIVE Macro to prevent function from being optimized out
Module.ccall JavaScript method to call C++ functions
Module._malloc Allocate memory in WebAssembly heap
Module._free Free allocated memory in WebAssembly heap
Module.HEAP32 Int32Array view of WebAssembly memory

Remember, WebAssembly and C++ open up a world of possibilities for web development. The sky's the limit! Keep coding, keep learning, and who knows? Maybe you'll be the one teaching this course in a few years!

Credits: Image by storyset