---
title: Intro a WebAssembly (wasm).
tags: DAW, wasm
---
<div style="width: 30%; margin-left: auto;">

</div>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Llicència de Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />Aquesta obra està subjecta a una llicència de <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Reconeixement-CompartirIgual 4.0 Internacional de Creative Commons</a>
# Intro a Web Assembly.

Segons la pròpia [pàgina oficial](https://webassembly.org), WebAssembly es pot definir com:
> WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.
## Corolaris que s'extreuen directament de la definició:
1. WebAssembly **no** es javascript, és un format binari totalment diferent.
2. WebAssembly corre sobre una màquina virtual basada en pila.
3. WebAssembly està dissenyat per a poderse compilar a partir de diferents llenguatges i facilitar el desplegament a través de la web.
## Principis de disseny de WebAssembly:
1. Efficient i ràpid: L'objectiu de la màquina de pila Wasm, és apropar-se a la velocitat nativa.
2. Segur: L'execució de WebAssembly es produeix dins d'un 'sand box' i en el cas de la web, reforça les polítiques d'origen comú: 'same origin' i polítiques de seguretat del navegador.
3. Oberta i depurable: WebAssembly està dissenyada per a poder representar-se en forma de text agradablement formatat per motius de depuració, proves, optimització, aprenentatge o inclús per a poder escriure programes a ma en format wasm.
4. Part de la plataforma web: Els mòduls de WebAssembly són capaços de fer crides al context de JavaScrip i accedir a la funcionalitat del navegador a través de la mateixa API a la que accedeix JavaScript.
## [Conceptes clau](https://developer.mozilla.org/en-US/docs/WebAssembly/Concepts#webassembly_key_concepts):
1. Module: Represents a WebAssembly binary that has been compiled by the browser into executable machine code. A Module is stateless and thus, like a Blob, can be explicitly shared between windows and workers (via postMessage()). A Module declares imports and exports just like an ES module.
2. Memory: A resizable ArrayBuffer that contains the linear array of bytes read and written by WebAssembly's low-level memory access instructions.
3. Table: A resizable typed array of references (e.g. to functions) that could not otherwise be stored as raw bytes in Memory (for safety and portability reasons).
4. Instance: A Module paired with all the state it uses at runtime including a Memory, Table, and set of imported values. An Instance is like an ES module that has been loaded into a particular global with a particular set of imports.
## Diferents maneres d'utilitzar WebAssembly:
1. Portar una aplicació C/C++ amb Emscripten.
2. Escriure o generar WebAssembly directament a nivel d'ensamblador.
3. Escriure una aplicació en Rust i compilar a WebAssembly.
4. Utilitzar AssemblyScript que s'assembla a TypeScript es compila a un binari de WebAssembly.
## Generant mòduls wasm a partir de codi C/C++.
### Instal·lació d'Emscripten.
Les passes necessàries per instal·lar el SDK d'Emscripten les podeu trobar a la [pàgina oficial](https://emscripten.org/docs/getting_started/downloads.html), però us aconsello que comenceu fent ús de la [imatge Docker](https://hub.docker.com/r/emscripten/emsdk#!) preparada a tal efecte. Amb la següent comanda, obtindreu accés a la terminal del contenidor amb la carpeta on heu executat l'ordre montada com a un volum Docker a la ruta '/src' del contenidor.
```bash=
docker run -it -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk bash
```
```bash=
xavi@portatil:~/Documentos/wasm$ docker run -it -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk bash
groups: cannot find name for group ID 131
emscripten@4fa4fc854c38:/src$ ls
favicon.ico hello.html hello.js hello.wasm hello_wasm.html helloworld.cpp helloworld.js helloworld.wasm
emscripten@4fa4fc854c38:/src$
```
### Generació i compilació del codi C++ d'exemple.
Partirem d'un fitxer helloworld.cpp típic:
```cpp=
#include <iostream>
int main() {
std::cout << "Hello World!\n";
return 0;
}
```
I el compilarem amb l'eina emcc que tenim preparada al contenidor:
```bash=
emscripten@4fa4fc854c38:/src$ emcc helloworld.cpp -o helloworld.js
cache:INFO: generating system asset: symbol_lists/27772d71a5153dd93f16df2df7cc5d46369da5ac.json... (this will be cached in "/emsdk/upstream/emscripten/cache/symbol_lists/27772d71a5153dd93f16df2df7cc5d46369da5ac.json" for subsequent builds)
cache:INFO: - ok
```
Ara ja tenim el nostre mòdul .wasm i el _codi adhesiu_ ('glue code'):
```bash=
emscripten@4fa4fc854c38:/src$ ls -l
total 360
-rw-rw-r-- 1 emscripten emscripten 16655 Feb 28 07:16 favicon.ico
-rw-rw-r-- 1 emscripten 131 246 Feb 28 08:19 hello_wasm.html
-rw-rw-r-- 1 emscripten 131 85 Feb 28 08:15 helloworld.cpp
-rw-r--r-- 1 emscripten 131 175276 Feb 28 09:40 helloworld.js
-rwxr-xr-x 1 emscripten 131 161689 Feb 28 09:40 helloworld.wasm
```
El fitxer hello_wasm.html ha estat creat a ma. També és possible que el propi compilador emcc ens generi un fitxer html, però no és tant instructiu com aquest codi minimalista escrit a ma:
```htmlembedded=
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello wasm!</title>
</head>
<body>
<script src="helloworld.js"></script>
</body>
```
El resultat el podem veure a la següent imatge:

### Integració del codi C al navegador.
#### ccall i cwrap
Utilitzarem els seguents fitxers:
1. Un programa en c: wrapping.c
2. Un document html: wrapping.html
```clike=
// wrapping.c
#include <stdio.h>
#include "emscripten.h"
EMSCRIPTEN_KEEPALIVE int suma(int a, int b) {
return a + b;
}
EMSCRIPTEN_KEEPALIVE int main() {
printf("Hello World!, %d\n", suma(4, 6));
return 0;
}
```
```htmlembedded=
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>wrapping.html</title>
<script src="wrapping.js"></script>
<script>
function run_wasm() {
var suma = Module.cwrap("suma", "number", ["number","number"]);
var result = Module.ccall(
"main",
"number",
null,
null
);
console.log(result);
var a = document.querySelector("#a").value;
var b = document.querySelector("#b").value;
var result = Module.ccall(
"suma",
"number",
["number","number"],
[a, b]
);
console.log(result);
console.log(suma(a,b));
}
</script>
</head>
<body>
<input type="number" id="a">
<input type="number" id="b">
<button onclick="run_wasm()">Run Wasm</button>
</body>
</html>
```
I compilarem el codi amb el següent modificador:
```bash=
emcc wrapping.c -o wrapping.js -sEXPORTED_RUNTIME_METHODS=ccall,cwrap
```
