Introduction à WebAssembly et C++
\n\nLe développement web moderne cherche constamment des moyens d'améliorer les performances. WebAssembly (Wasm) est un format d'instructions binaires de bas niveau qui s'exécute dans le navigateur à une vitesse proche de celle du code natif. Combiné avec C++, l'un des langages de programmation les plus rapides et les plus puissants, Wasm ouvre de nouveaux horizons : des jeux et simulations haute performance aux algorithmes complexes de traitement de données directement dans le navigateur.
\n\nDans cet article, nous parcourrons le chemin des bases à l'application pratique : nous verrons comment compiler du code C++ en WebAssembly, l'exécuter dans le navigateur et l'optimiser pour des performances maximales.
\n\n1. Outillage et configuration de l'environnement
\n\nL'outil principal pour compiler le C++ en WebAssembly est la suite de compilateurs Emscripten. Il traduit le bytecode LLVM en Wasm et génère automatiquement le code de liaison JavaScript (glue code) nécessaire au chargement du module.
\n\nInstallation d'Emscripten
\nLa méthode d'installation recommandée est via le gestionnaire de paquets emsdk :
# Cloner le dépôt\ngit clone https://github.com/emscripten-core/emsdk.git\ncd emsdk\n\n# Installer et activer la dernière version\n./emsdk install latest\n./emsdk activate latest\n\n# Ajouter les variables d'environnement (variables shell)\nsource ./emsdk_env.sh\n\nAprès l'installation, vous disposerez des commandes emcc (compilateur) et em++ (compilateur C++), qui sont des surcouches de Clang.
2. Compilation du C++ en WebAssembly
\n\nPrenons un exemple très simple. Créons un fichier hello.cpp :
#include <emscripten/emscripten.h>\n\n// Fonction accessible depuis JavaScript\nextern "C" {\n int EMSCRIPTEN_KEEPALIVE add(int a, int b) {\n return a + b;\n }\n}\n\nUn élément important est la macro EMSCRIPTEN_KEEPALIVE. Elle empêche la suppression de la fonction par l'optimiseur et la rend exportable.
Compilons notre code :
\n\nem++ hello.cpp -o hello.html -s WASM=1 -s EXPORTED_FUNCTIONS='["_add"]' -O3\n\nDétaillons les drapeaux :
\n- \n
-o hello.html— crée un fichier HTML avec un exemple d'exécution. \n -s WASM=1— spécifie explicitement la génération Wasm (activé par défaut). \n -s EXPORTED_FUNCTIONS='["_add"]'— liste des fonctions exportées (avec le préfixe_). \n -O3— niveau d'optimisation élevé. \n
En résultat, nous obtenons trois fichiers : hello.html, hello.js (glue code) et hello.wasm.
3. Interaction avec JavaScript
\n\nAprès la compilation, nous pouvons appeler notre fonction C++ depuis JavaScript. Voici un code minimal de chargement du module :
\n\n<!DOCTYPE html>\n<html>\n<head>\n <script>\n var Module = {};\n Module.onRuntimeInitialized = function() {\n // La fonction add est maintenant disponible\n var result = Module._add(5, 7);\n console.log("Résultat : " + result); // 12\n };\n </script>\n <script src="hello.js"></script>\n</head>\n<body></body>\n</html>\n\nPoints clés :
\n- \n
Module.onRuntimeInitialized— événement déclenché après le chargement du module Wasm. \n - Les noms de fonctions en JS reçoivent le préfixe
_(par exemple,_add). \n - Pour transmettre des structures de données complexes (chaînes, tableaux), on utilise
Module._mallocet des pointeurs. \n
Transmission de chaînes
\nExemple de fonction retournant un message de salutation :
\n\n// Code C++\nextern "C" {\n const char* EMSCRIPTEN_KEEPALIVE greet(const char* name) {\n static std::string msg = "Bonjour, " + std::string(name) + "!";\n return msg.c_str();\n }\n}\n\nEn JavaS