Introdução ao WebAssembly e C++
\n\nO desenvolvimento web moderno está constantemente buscando maneiras de aumentar o desempenho. WebAssembly (Wasm) é um formato de instrução binário de baixo nível que é executado no navegador com velocidade próxima à nativa. Em combinação com C++, uma das linguagens de programação mais rápidas e poderosas, o Wasm abre novos horizontes: desde jogos e simulações de alto desempenho até algoritmos complexos de processamento de dados diretamente no navegador.
\n\nNeste artigo, percorreremos o caminho desde o básico até a aplicação prática: analisaremos como compilar código C++ para WebAssembly, executá-lo no navegador e otimizá-lo para máximo desempenho.
\n\n1. Ferramentas e Configuração do Ambiente
\n\nA principal ferramenta para compilar C++ para WebAssembly é o conjunto de compiladores Emscripten. Ele traduz o bytecode LLVM para Wasm e gera automaticamente o código de ligação JavaScript (glue code) necessário para carregar o módulo.
\n\nInstalação do Emscripten
\nA maneira recomendada de instalar é através do gerenciador de pacotes emsdk:
# Clonamos o repositório\ngit clone https://github.com/emscripten-core/emsdk.git\ncd emsdk\n\n# Instalamos e ativamos a versão mais recente\n./emsdk install latest\n./emsdk activate latest\n\n# Adicionamos as variáveis de ambiente (variáveis de shell)\nsource ./emsdk_env.sh\n\nApós a instalação, você terá os comandos emcc (compilador) e em++ (compilador C++), que são wrappers sobre o Clang.
2. Compilação de C++ para WebAssembly
\n\nVamos considerar um exemplo simples. Criaremos o arquivo hello.cpp:
#include <emscripten/emscripten.h>\n\n// Função acessível a partir do JavaScript\nextern "C" {\n int EMSCRIPTEN_KEEPALIVE add(int a, int b) {\n return a + b;\n }\n}\n\nUm elemento importante é a macro EMSCRIPTEN_KEEPALIVE. Ela impede que a função seja removida pelo otimizador e a torna exportável.
Vamos compilar nosso código:
\n\nem++ hello.cpp -o hello.html -s WASM=1 -s EXPORTED_FUNCTIONS='["_add"]' -O3\n\nVamos analisar as flags:
\n- \n
-o hello.html— cria um arquivo HTML com um exemplo de execução. \n -s WASM=1— especifica explicitamente a geração de Wasm (ativado por padrão). \n -s EXPORTED_FUNCTIONS='["_add"]'— lista de funções exportadas (com o prefixo_). \n -O3— alto nível de otimização. \n
Como resultado, obteremos três arquivos: hello.html, hello.js (glue code) e hello.wasm.
3. Interação com JavaScript
\n\nApós a compilação, podemos chamar nossa função C++ a partir do JavaScript. Aqui está um código mínimo para carregar o módulo:
\n\n<!DOCTYPE html>\n<html>\n<head>\n <script>\n var Module = {};\n Module.onRuntimeInitialized = function() {\n // A função add agora está disponível\n var result = Module._add(5, 7);\n console.log("Resultado: " + result); // 12\n };\n </script>\n <script src="hello.js"></script>\n</head>\n<body></body>\n</html>\n\nPontos-chave:
\n- \n
Module.onRuntimeInitialized— evento acionado após o carregamento do módulo Wasm. \n - Os nomes das funções em JS recebem o prefixo
_(por exemplo,_add). \n - Para passar estruturas de dados complexas (strings, arrays), são usados
Module._malloce ponteiros. \n
Passando Strings
\nExemplo de uma função que retorna uma saudação:
\n\n// Código C++\nextern "C" {\n const char* EMSCRIPTEN_KEEPALIVE greet(const char* name) {\n static std::string msg = "Olá, " + std::string(name) + "!";\n return msg.c_str();\n }\n}\n\nEm JavaS