<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Wasm on kenji.blog</title><link>http://kenji.blog/es/tags/wasm/</link><description>Recent content in Wasm on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>es</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 10:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/es/tags/wasm/index.xml" rel="self" type="application/rss+xml"/><item><title>Generar WebAssembly (Wasm) desde C++ y Rust para ejecutar en el navegador</title><link>http://kenji.blog/es/p/webassembly-wasm-from-cpp-and-rust/</link><pubDate>Sat, 12 Sep 2026 10:00:00 +0900</pubDate><guid>http://kenji.blog/es/p/webassembly-wasm-from-cpp-and-rust/</guid><description>&lt;img src="http://kenji.blog/p/webassembly-wasm-from-cpp-and-rust/img/eyecatch.jpg" alt="Featured image of post Generar WebAssembly (Wasm) desde C++ y Rust para ejecutar en el navegador" />&lt;h2 id="1-introducción">1. Introducción
&lt;/h2>&lt;p>En el desarrollo web moderno, JavaScript (y TypeScript) ha consolidado su posición como el único lenguaje de programación que se ejecuta en el navegador durante mucho tiempo. Sin embargo, en los últimos años, ha aumentado la demanda de realizar cálculos más avanzados en el propio navegador, como el procesamiento de imágenes, la codificación de video, los juegos en 3D y la simulación física. Es aquí donde entra &lt;strong>WebAssembly (conocido como Wasm)&lt;/strong>.&lt;/p>
&lt;p>En este artículo, comenzaremos desde los fundamentos de WebAssembly, y explicaremos detalladamente los procedimientos y la estructura interna para generar Wasm a partir de dos potentes lenguajes de programación de sistemas: C++ (usando Emscripten) y Rust (usando &lt;code>wasm-pack&lt;/code>), y cómo integrarlos con el entorno de JavaScript. Además, profundizaremos en la gestión de los límites de memoria, cómo pasar datos complejos como cadenas y matrices, la sobrecarga de rendimiento y el formato binario de Wasm (&lt;code>.wasm&lt;/code>).&lt;/p>
&lt;h2 id="2-descripción-general-y-arquitectura-de-webassembly-wasm">2. Descripción general y arquitectura de WebAssembly (Wasm)
&lt;/h2>&lt;p>WebAssembly es un formato de instrucciones binarias para una máquina virtual basada en pila. Está diseñado como un &amp;ldquo;objetivo de compilación portátil&amp;rdquo; que se puede compilar a partir de lenguajes como C/C++, Rust, Go, Zig, etc., con el objetivo de ejecutarse a una velocidad cercana a la nativa en los navegadores web.&lt;/p>
&lt;p>El siguiente diagrama muestra el flujo general de la cadena de herramientas desde que se genera WebAssembly a partir de C++ y Rust hasta que se ejecuta en el navegador.&lt;/p>
&lt;div class="mermaid">graph TD
A["Código fuente C++ (.cpp)"] --> B["Emscripten (clang/LLVM)"]
B --> C["Salida .wasm"]
B --> D["Salida JS de enlace"]
E["Código fuente Rust (.rs)"] --> F["cargo / rustc / LLVM"]
F --> G["wasm-bindgen / wasm-pack"]
G --> H["Salida .wasm"]
G --> I["Salida de envoltorios JS"]
C --> J["Navegador (V8 / SpiderMonkey / JavaScriptCore)"]
D --> J
H --> J
I --> J&lt;/div>
&lt;p>Wasm no reemplaza a JavaScript. Está diseñado para funcionar junto con JavaScript, delegando las tareas de gran carga computacional a Wasm, aprovechando así los puntos fuertes de cada uno.&lt;/p>
&lt;h2 id="3-desafío-matemático-cálculo-del-conjunto-de-mandelbrot">3. Desafío matemático: Cálculo del conjunto de Mandelbrot
&lt;/h2>&lt;p>En este artículo, utilizaremos el algoritmo de dibujo del &amp;ldquo;conjunto de Mandelbrot&amp;rdquo;, que impone una gran carga en la CPU, para implementarlo en C++ y Rust.&lt;/p>
&lt;p>El conjunto de Mandelbrot se define mediante la siguiente relación de recurrencia compleja:&lt;/p>
$$ z_{n+1} = z_n^2 + c $$
&lt;p>Aquí, $z$ y $c$ son números complejos, y el cálculo comienza desde $z_0 = 0$. El conjunto de Mandelbrot es el conjunto de $c$ para los cuales el valor absoluto de $z_n$ no diverge cuando el cálculo se repite infinitamente para un número complejo $c$. Generalmente, al calcular en una computadora, se considera que ha divergido bajo la siguiente condición:&lt;/p>
$$ |z_n| > 2 $$
&lt;p>Es decir, para la parte real $x$ y la parte imaginaria $y$, se determina si se cumple la siguiente condición hasta un número máximo de iteraciones (por ejemplo, $N = 1000$):&lt;/p>
$$ x^2 + y^2 > 4 $$
&lt;h2 id="4-enfoque-con-c-y-emscripten">4. Enfoque con C++ y Emscripten
&lt;/h2>&lt;p>Emscripten es una cadena de herramientas de compilación basada en LLVM y es el estándar de facto para compilar código C/C++ a WebAssembly. Proporciona un potente entorno de ejecución que emula llamadas al sistema POSIX con la API del navegador (Web API).&lt;/p>
&lt;h3 id="código-de-implementación-en-c">Código de implementación en C++
&lt;/h3>&lt;p>El siguiente código de C++ calcula el conjunto de Mandelbrot del ancho y alto especificados y almacena el resultado (el número de iteraciones de cada píxel) en una matriz unidimensional.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;emscripten/emscripten.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Especificar enlazado C para que pueda ser llamado desde JavaScript
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">extern&lt;/span> &lt;span class="s">&amp;#34;C&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Devuelve un puntero al búfer que almacena el resultado del cálculo
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">EMSCRIPTEN_KEEPALIVE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="nf">compute_mandelbrot&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">width&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">height&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">max_iter&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Asignar el búfer como una variable estática (para simplificar)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">static&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">buffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">resize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">width&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">height&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">row&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">row&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">height&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">row&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">col&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">col&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">width&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">col&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">double&lt;/span> &lt;span class="n">c_re&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">col&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">width&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mf">2.0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">4.0&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">width&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">double&lt;/span> &lt;span class="n">c_im&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">row&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">height&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mf">2.0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">4.0&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">width&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">double&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">iteration&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">4&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">iteration&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">max_iter&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">double&lt;/span> &lt;span class="n">x_new&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">c_re&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">c_im&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x_new&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">iteration&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">buffer&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">row&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">width&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">col&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">iteration&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Función para liberar memoria (si es necesario)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">EMSCRIPTEN_KEEPALIVE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">free_buffer&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="compilación-y-llamada-desde-javascript">Compilación y llamada desde JavaScript
&lt;/h3>&lt;p>Compilaremos este código usando Emscripten.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">emcc mandelbrot.cpp -O3 -s &lt;span class="nv">WASM&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> -s &lt;span class="nv">EXPORTED_FUNCTIONS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;[&amp;#39;_compute_mandelbrot&amp;#39;, &amp;#39;_malloc&amp;#39;, &amp;#39;_free&amp;#39;]&amp;#34;&lt;/span> -s &lt;span class="nv">EXPORTED_RUNTIME_METHODS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;[&amp;#39;ccall&amp;#39;, &amp;#39;cwrap&amp;#39;]&amp;#34;&lt;/span> -o mandelbrot.js
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>En el lado de JavaScript, se carga el código de enlace (&lt;code>mandelbrot.js&lt;/code>) generado por Emscripten y se llama usando la API de WebAssembly como se muestra a continuación.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">Module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">onRuntimeInitialized&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">width&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">800&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">height&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">600&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">maxIter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Llamar a la función C++ y obtener el puntero
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kr">const&lt;/span> &lt;span class="nx">resultPtr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">Module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ccall&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;compute_mandelbrot&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// Nombre de la función en C
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="s1">&amp;#39;number&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// Tipo de valor de retorno (el puntero es number)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;number&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;number&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;number&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="c1">// Tipos de los argumentos
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nx">width&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">height&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">maxIter&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Leer directamente los datos de la matriz de la memoria lineal (Module.HEAP32)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kr">const&lt;/span> &lt;span class="nx">numElements&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">width&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="nx">height&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">resultView&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="nx">Int32Array&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">Module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">HEAP32&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">resultPtr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">numElements&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Cálculo completado. Datos del primer píxel: &amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="nx">resultView&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="5-enfoque-con-rust-y-wasm-pack">5. Enfoque con Rust y &lt;code>wasm-pack&lt;/code>
&lt;/h2>&lt;p>Rust ofrece soporte de primera clase para WebAssembly, y el uso de las herramientas &lt;code>wasm-bindgen&lt;/code> y &lt;code>wasm-pack&lt;/code> permite una alta integración entre JavaScript y Rust. Mientras que Emscripten adopta el enfoque de &amp;ldquo;llevar un enorme tiempo de ejecución de C/C++ al navegador&amp;rdquo;, el &lt;code>wasm-pack&lt;/code> de Rust adopta el enfoque de &amp;ldquo;generar solo los enlaces (código de enlace JS) mínimos necesarios&amp;rdquo;.&lt;/p>
&lt;h3 id="código-de-implementación-en-rust">Código de implementación en Rust
&lt;/h3>&lt;p>Crearemos un proyecto de Cargo y especificaremos &lt;code>cdylib&lt;/code> y &lt;code>wasm-bindgen&lt;/code> en &lt;code>Cargo.toml&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">lib&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">crate-type&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;cdylib&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">dependencies&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">wasm-bindgen&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;0.2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>A continuación, escribimos la implementación en &lt;code>src/lib.rs&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="k">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">wasm_bindgen&lt;/span>::&lt;span class="n">prelude&lt;/span>::&lt;span class="o">*&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="cp">#[wasm_bindgen]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">pub&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">compute_mandelbrot_rust&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">width&lt;/span>: &lt;span class="kt">usize&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">height&lt;/span>: &lt;span class="kt">usize&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">max_iter&lt;/span>: &lt;span class="kt">u32&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>-&amp;gt; &lt;span class="nb">Vec&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">i32&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="fm">vec!&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">width&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">height&lt;/span>&lt;span class="p">];&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">row&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">..&lt;/span>&lt;span class="n">height&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">col&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">..&lt;/span>&lt;span class="n">width&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">c_re&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">col&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">f64&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">width&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">f64&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mf">2.0&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mf">4.0&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">width&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">f64&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">c_im&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">row&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">f64&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">height&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">f64&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mf">2.0&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mf">4.0&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">width&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">f64&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mf">0.0&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mf">0.0&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">iteration&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">while&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;lt;=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mf">4.0&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;amp;&amp;amp;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">iteration&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">max_iter&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">x_new&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">c_re&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mf">2.0&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">c_im&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">x_new&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">iteration&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">row&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">width&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">col&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">iteration&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">i32&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="compilación-y-llamada-desde-javascript-1">Compilación y llamada desde JavaScript
&lt;/h3>&lt;p>Construimos con el comando &lt;code>wasm-pack&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">wasm-pack build --target web
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Importamos el paquete generado desde JavaScript. Gracias a &lt;code>wasm-bindgen&lt;/code>, el &lt;code>Vec&amp;lt;i32&amp;gt;&lt;/code> de Rust se convierte automáticamente en un &lt;code>Int32Array&lt;/code> de JavaScript (ocultando la manipulación de punteros).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="nx">init&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">compute_mandelbrot_rust&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="nx">from&lt;/span> &lt;span class="s1">&amp;#39;./pkg/mandelbrot_wasm.js&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">async&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="nx">run&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">await&lt;/span> &lt;span class="nx">init&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// Inicialización del módulo WebAssembly
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">width&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">800&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">height&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">600&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">maxIter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Se puede recibir el resultado directamente como una matriz de JavaScript
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kr">const&lt;/span> &lt;span class="nx">resultView&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">compute_mandelbrot_rust&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">width&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">height&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">maxIter&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Cálculo completado. Datos del primer píxel: &amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="nx">resultView&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">run&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="6-profundización-límites-de-memoria-y-paso-de-tipos-de-datos">6. Profundización: Límites de memoria y paso de tipos de datos
&lt;/h2>&lt;p>Uno de los conceptos más importantes en WebAssembly es la &amp;ldquo;memoria lineal (Linear Memory)&amp;rdquo;. El código Wasm no puede acceder directamente al espacio de memoria del anfitrión (navegador), sino que se le asigna un enorme &lt;code>ArrayBuffer&lt;/code> aislado. Esta es la memoria lineal.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant JS as "Entorno JavaScript"
participant Wasm as "Tiempo de ejecución WebAssembly"
participant Mem as "Memoria Lineal (ArrayBuffer)"
JS->>Wasm: "Llamar calculate(10, 20)"
note over JS,Wasm: "Primitivos (int, float) pasados directamente por Registros/Pila"
Wasm-->>JS: "Retornar 30"
note over JS, Mem: "Para datos complejos (Cadenas, Matrices)"
JS->>Mem: "Escribir Cadena en Memoria"
JS->>Wasm: "Llamar process_string(puntero, longitud)"
Wasm->>Mem: "Leer desde puntero"
Wasm->>Mem: "Escribir resultado en nuevo puntero"
Wasm-->>JS: "Retornar nuevo puntero y longitud"
JS->>Mem: "Leer datos de resultado de la memoria"&lt;/div>
&lt;h3 id="cómo-pasar-cadenas-y-matrices">Cómo pasar cadenas y matrices
&lt;/h3>&lt;p>Los enteros y los números de punto flotante (&lt;code>i32&lt;/code>, &lt;code>i64&lt;/code>, &lt;code>f32&lt;/code>, &lt;code>f64&lt;/code>) se pueden pasar directamente como valores a las funciones Wasm. Sin embargo, los tipos complejos como cadenas, matrices y estructuras no se pueden pasar directamente como firmas de funciones Wasm.&lt;/p>
&lt;p>&lt;strong>En el caso de Emscripten&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>Llamar a &lt;code>Module._malloc&lt;/code> en el lado de JS para asignar un área de memoria lineal en el lado de Wasm.&lt;/li>
&lt;li>Escribir los datos desde JS en la dirección de memoria asignada (puntero) usando algo como &lt;code>Module.HEAPU8.set()&lt;/code>.&lt;/li>
&lt;li>Pasar el puntero a la función de C++.&lt;/li>
&lt;li>Después del cálculo, leer el resultado desde el puntero en el lado de JS y finalmente llamar a &lt;code>Module._free&lt;/code>.&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>En el caso de wasm-bindgen (Rust)&lt;/strong>:
El tedioso flujo de gestión de memoria anterior se oculta completamente dentro del código de enlace generado automáticamente (envoltorio JS). Cuando pasas un simple &lt;code>String&lt;/code> o &lt;code>Array&lt;/code> desde el lado de JS a la función de Rust, detrás de escena se realiza automáticamente una serie de operaciones: asignación de búfer (equivalente a &lt;code>malloc&lt;/code>), copia, paso de puntero y liberación de memoria.&lt;/p>
&lt;h2 id="7-sobrecarga-de-rendimiento-y-optimización">7. Sobrecarga de rendimiento y optimización
&lt;/h2>&lt;p>WebAssembly se puede ejecutar a una velocidad cercana a la nativa, pero existe una sobrecarga en la &amp;ldquo;comunicación que cruza el límite entre JavaScript y WebAssembly (Interop)&amp;rdquo;.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Sobrecarga de llamada&lt;/strong>: Es el costo de conmutación para que el motor de JavaScript llame a una función Wasm. Aunque actualmente está muy optimizado, se debe evitar el diseño de llamar a funciones muy ligeras decenas de miles de veces por fotograma.&lt;/li>
&lt;li>&lt;strong>Costo de copia de memoria&lt;/strong>: Al pasar cadenas o matrices a Wasm, se produce una copia de datos desde la memoria gestionada por la recolección de basura de JS a la memoria lineal de Wasm (ArrayBuffer). Si pasas una gran cantidad de datos, se requiere un diseño de &amp;ldquo;copia cero&amp;rdquo; donde los datos se construyen en la memoria Wasm desde el principio y se accede desde el lado de JS a través de una vista de TypedArray (como &lt;code>Uint8Array&lt;/code>).&lt;/li>
&lt;/ul>
&lt;p>Por ejemplo, en motores de juegos y motores de física, es común la arquitectura en la que todo el estado se mantiene dentro de la memoria lineal de Wasm, y JavaScript solo se encarga de un disparador de &amp;ldquo;actualización&amp;rdquo; por fotograma y de la representación en pantalla (llamadas a la API WebGL/WebGPU).&lt;/p>
&lt;h2 id="8-anatomía-del-formato-binario-de-webassembly-wasm">8. Anatomía del formato binario de WebAssembly (.wasm)
&lt;/h2>&lt;p>Ahora, veamos la estructura interna del archivo &lt;code>.wasm&lt;/code> generado por el compilador. Los binarios de Wasm están compuestos por conjuntos de bloques lógicos llamados &amp;ldquo;secciones&amp;rdquo; con énfasis en la extensibilidad y la velocidad de análisis.&lt;/p>
&lt;div class="mermaid">graph TD
Root["Binario Wasm (.wasm)"] --> Magic["Número Mágico: '\0asm' (0x00 0x61 0x73 0x6D)"]
Root --> Version["Versión: 1 (0x01 0x00 0x00 0x00)"]
Root --> Sections["Secciones"]
Sections --> S1["1: Sección de Tipos (Firmas de Funciones)"]
Sections --> S2["2: Sección de Importaciones (Funciones JS a importar)"]
Sections --> S3["3: Sección de Funciones (Declaraciones de Funciones)"]
Sections --> S4["4: Sección de Tablas (Punteros a Funciones)"]
Sections --> S5["5: Sección de Memoria (Tamaño de la Memoria Lineal)"]
Sections --> S7["7: Sección de Exportaciones (Funciones expuestas a JS)"]
Sections --> S10["10: Sección de Código (Instrucciones de Bytecode Wasm)"]
Sections --> S11["11: Sección de Datos (Cadenas/Constantes Estáticas)"]&lt;/div>
&lt;p>El número mágico del archivo siempre comienza con &lt;code>0x00 0x61 0x73 0x6D&lt;/code> (&lt;code>\0asm&lt;/code>). Cada sección que sigue a esto tiene su propia ID.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Type Section&lt;/strong>: Define todas las firmas de funciones (tipos de argumentos y valores de retorno) utilizadas.&lt;/li>
&lt;li>&lt;strong>Import Section&lt;/strong>: Lista de funciones o memoria proporcionadas por el entorno JavaScript a Wasm. Por ejemplo, si llamas a &lt;code>console.log&lt;/code> desde C++, se declara aquí.&lt;/li>
&lt;li>&lt;strong>Code Section&lt;/strong>: Almacena las instrucciones de código de bytes reales (&lt;code>i32.add&lt;/code>, &lt;code>call&lt;/code>, &lt;code>loop&lt;/code>, etc.). Al ser una máquina de pila, es un formato en el que se apilan los operandos y se llaman a las instrucciones operativas.&lt;/li>
&lt;li>&lt;strong>Data Section&lt;/strong>: Las cadenas literales estáticas o datos de inicialización definidos en el código de C++ o Rust se cargan en la memoria lineal desde esta sección.&lt;/li>
&lt;/ul>
&lt;p>El motor de Wasm del navegador logra una aceleración dramática del inicio mediante la compilación en flujo de estas secciones (compilación en código de máquina en paralelo mientras se descarga).&lt;/p>
&lt;h2 id="9-c-vs-rust-cuál-deberías-elegir">9. C++ vs Rust: ¿Cuál deberías elegir?
&lt;/h2>&lt;p>En la generación de WebAssembly, elegir entre C++ y Rust depende en gran medida de los requisitos de tu proyecto y de los recursos existentes.&lt;/p>
&lt;p>&lt;strong>Casos en los que deberías elegir C++ / Emscripten&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Cuando deseas portar librerías C/C++ existentes (FFmpeg, OpenCV, SQLite, etc.) al navegador.&lt;/li>
&lt;li>Proyectos de migración de juegos que desean utilizar directamente funciones de conversión de API gráficas como OpenGL a WebGL (capa de emulación GL de Emscripten).&lt;/li>
&lt;li>Cuando se requieren funciones del sistema operativo virtualizadas, como la emulación del sistema de archivos (MEMFS).&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Casos en los que deberías elegir Rust / wasm-pack&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Cuando desarrollas módulos de alto rendimiento desde cero como parte de una aplicación web.&lt;/li>
&lt;li>Cuando deseas una integración fuerte y segura de tipos con el ecosistema de JavaScript (módulos NPM y TypeScript).&lt;/li>
&lt;li>Cuando requieres un tamaño binario relativamente pequeño y una gestión de memoria segura (modelo de propiedad de Rust).&lt;/li>
&lt;li>Cuando deseas beneficiarte de una cadena de herramientas moderna como la gestión de dependencias con Cargo.&lt;/li>
&lt;/ul>
&lt;h2 id="10-resumen">10. Resumen
&lt;/h2>&lt;p>WebAssembly es una tecnología innovadora para ejecutar procesos computacionalmente intensivos en el navegador. Tanto el enfoque de portabilidad completa (full-stack) utilizando C++ y Emscripten, como el enfoque modular acoplado estrechamente con JavaScript utilizando Rust y wasm-bindgen, tienen sus propios puntos fuertes.&lt;/p>
&lt;p>En cálculos como el conjunto de Mandelbrot, se espera que Wasm mejore la velocidad de varias a decenas de veces en comparación con JavaScript por sí solo. Sin embargo, no podrás extraer el verdadero rendimiento a menos que comprendas correctamente el mecanismo del límite de memoria entre Wasm y JS y diseñes para evitar copias de memoria innecesarias.&lt;/p>
&lt;p>Esperamos que a través de este artículo hayas profundizado en tu comprensión del flujo completo de generar Wasm a partir de C++ y Rust y ejecutarlo en el navegador, así como de la arquitectura detrás de él. En el desarrollo de aplicaciones web de próxima generación, WebAssembly sin duda será un arma poderosa.&lt;/p></description></item></channel></rss>