WebAssembly - Working with C

Introduction to WebAssembly and C

Hello there, future coding wizards! Today, we're embarking on an exciting journey into the world of WebAssembly and C. As your friendly neighborhood computer science teacher, I'm here to guide you through this adventure with the same enthusiasm I had when I first discovered the magic of coding. So, buckle up and let's dive in!

WebAssembly - Working with C

What is WebAssembly?

WebAssembly, or Wasm for short, is like a secret language that allows your web browser to run super-fast code. Imagine if your browser suddenly got superpowers - that's what WebAssembly does! It lets us write code in languages like C and run it in the browser at near-native speed.

Why C with WebAssembly?

Now, you might wonder, "Why C? Isn't that an old language?" Well, my young padawans, C is like the wise grandparent of programming languages. It's been around for ages, and for good reason! C is fast, efficient, and has a ton of existing code that we can tap into. By using C with WebAssembly, we're bringing this powerhouse to the web.

Setting Up the Environment

Before we start coding, we need to set up our digital workshop. Don't worry; it's easier than assembling IKEA furniture!

Installing Emscripten

Emscripten is our magical tool that will transform C code into WebAssembly. Here's how to get it:

  1. Open your terminal (don't be scared, it's just a text-based friend)
  2. Run the following commands:
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

Congratulations! You've just set up your WebAssembly laboratory.

Your First WebAssembly Program

Let's start with a simple "Hello, World!" program. It's like the first words of a baby, but in code!

Writing the C Code

Create a file named hello.c and add this code:

#include <stdio.h>

int main() {
    printf("Hello, WebAssembly World!\n");
    return 0;
}

This little snippet is telling the computer to print our greeting. It's like teaching a parrot to say "Hello" but much cooler!

Compiling to WebAssembly

Now, let's turn our C code into WebAssembly. In your terminal, run:

emcc hello.c -s WASM=1 -o hello.html

This command is like waving a magic wand. It creates three files: hello.html, hello.js, and hello.wasm.

Running Your WebAssembly Program

Open the hello.html file in your browser. You should see "Hello, WebAssembly World!" printed. Congratulations! You've just run your first WebAssembly program!

Working with Functions

Now that we've said hello, let's do some actual work. We'll create a function to add two numbers.

Creating a Simple Add Function

Create a new file called math.c:

#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
    return a + b;
}

The EMSCRIPTEN_KEEPALIVE is like telling the compiler, "Hey, this function is important! Keep it around!"

Compiling the Function

Compile it with:

emcc math.c -s WASM=1 -s EXPORTED_FUNCTIONS='["_add"]' -o math.js

This creates math.js and math.wasm.

Using the Function in JavaScript

Now, let's use our C function in JavaScript. Create an index.html file:

<!DOCTYPE html>
<html>
<head>
    <title>WebAssembly Math</title>
</head>
<body>
    <h1>WebAssembly Math</h1>
    <p>Result: <span id="result"></span></p>
    <script src="math.js"></script>
    <script>
        Module.onRuntimeInitialized = function() {
            var result = Module._add(5, 7);
            document.getElementById('result').textContent = result;
        };
    </script>
</body>
</html>

Open this in your browser, and you'll see the result of 5 + 7!

Working with Memory

Now, let's get a bit more advanced and work with memory. This is like giving your WebAssembly superpowers access to a notebook where it can write things down.

Allocating and Using Memory

Create a file named memory.c:

#include <emscripten.h>
#include <stdlib.h>

EMSCRIPTEN_KEEPALIVE
int* create_array(int size) {
    return (int*)malloc(size * sizeof(int));
}

EMSCRIPTEN_KEEPALIVE
void fill_array(int* arr, int size) {
    for (int i = 0; i < size; i++) {
        arr[i] = i * 2;
    }
}

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

EMSCRIPTEN_KEEPALIVE
void free_array(int* arr) {
    free(arr);
}

Compile it with:

emcc memory.c -s WASM=1 -s EXPORTED_FUNCTIONS='["_create_array", "_fill_array", "_sum_array", "_free_array"]' -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' -o memory.js

Now, let's use these functions in JavaScript:

<!DOCTYPE html>
<html>
<head>
    <title>WebAssembly Memory</title>
</head>
<body>
    <h1>WebAssembly Memory Management</h1>
    <p>Sum of array: <span id="result"></span></p>
    <script src="memory.js"></script>
    <script>
        Module.onRuntimeInitialized = function() {
            const create_array = Module.cwrap('create_array', 'number', ['number']);
            const fill_array = Module.cwrap('fill_array', null, ['number', 'number']);
            const sum_array = Module.cwrap('sum_array', 'number', ['number', 'number']);
            const free_array = Module.cwrap('free_array', null, ['number']);

            const size = 10;
            const ptr = create_array(size);
            fill_array(ptr, size);
            const sum = sum_array(ptr, size);
            free_array(ptr);

            document.getElementById('result').textContent = sum;
        };
    </script>
</body>
</html>

This example shows how we can allocate memory, fill an array, compute a sum, and then free the memory - all using C functions called from JavaScript!

Conclusion

Congratulations, you've taken your first steps into the world of WebAssembly with C! We've covered the basics, from setting up your environment to working with memory. Remember, learning to code is like learning a new language - it takes practice and patience. But with each line of code you write, you're becoming more fluent in the language of computers.

As we wrap up, here's a table summarizing the key functions we've learned:

Function Description Example
printf() Prints text to the console printf("Hello, World!");
malloc() Allocates memory int arr = (int)malloc(size * sizeof(int));
free() Frees allocated memory free(arr);
EMSCRIPTEN_KEEPALIVE Prevents function from being optimized away EMSCRIPTEN_KEEPALIVE int add(int a, int b)

Keep coding, keep learning, and remember - in the world of programming, the only limit is your imagination! Happy coding, future tech superstars!

Credits: Image by storyset