Trabalhando com WebAssembly e C++: do Início ao Fim

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução ao WebAssembly e C++

\n\n

O 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\n

Neste 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\n

1. Ferramentas e Configuração do Ambiente

\n\n

A 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\n

Instalação do Emscripten

\n

A maneira recomendada de instalar é através do gerenciador de pacotes emsdk:

\n\n
# 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\n

Após a instalação, você terá os comandos emcc (compilador) e em++ (compilador C++), que são wrappers sobre o Clang.

\n\n

2. Compilação de C++ para WebAssembly

\n\n

Vamos considerar um exemplo simples. Criaremos o arquivo hello.cpp:

\n\n
#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\n

Um elemento importante é a macro EMSCRIPTEN_KEEPALIVE. Ela impede que a função seja removida pelo otimizador e a torna exportável.

\n\n

Vamos compilar nosso código:

\n\n
em++ hello.cpp -o hello.html -s WASM=1 -s EXPORTED_FUNCTIONS='["_add"]' -O3
\n\n

Vamos 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
\n\n

Como resultado, obteremos três arquivos: hello.html, hello.js (glue code) e hello.wasm.

\n\n

3. Interação com JavaScript

\n\n

Apó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\n

Pontos-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._malloc e ponteiros.
  • \n
\n\n

Passando Strings

\n

Exemplo 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\n

Em JavaS

Blogs

Book Recommendations