Hola Habr! Les presento la traducción del artículo
"Regreso al futuro con WebAssembly" de Attila Vágó.
Esta publicación es una traducción de un artículo que habla sobre las propiedades de WebAssemly y Emscripten. Artículo original en inglés.
El autor del artículo, Attila Vago, es un desarrollador senior de software en HMH. Escribe código, blogs y otras cosas en Internet. Un políglota de lenguajes de programación, una figura pragmática, apasionada por JavaScript y de fácil acceso. Persona fácilmente inspiradora e inspiradora con una fuerte adicción a las cosas para nerds, excelente comida, cerveza artesanal y Lego. Usado por Mac. Hace ejercicio a las 6 de la mañana.En 2011, escribí mi primera línea independiente de código no HTML (trabajé con él en 2007), y fue escrita en la muy buena C que enseñó el profesor David J. Malan de la Universidad de Harvard. Siempre será mi inspiración no solo para el estudio de la programación, sino también para el pensamiento programático. También recordé que hacer un sándwich de mantequilla de maní es solo para mí, pero es una tarea increíblemente difícil para una computadora e igualmente difícil para una persona que finge ser una computadora.
Si vio el video, al menos los primeros 18 minutos (sé que lleva mucho tiempo, pero la programación lleva tiempo), entonces comprenderá por qué hasta el día de hoy C está cerca de mi corazón. Para mi decepción, no lo aprendí, porque, seamos sinceros, para un desarrollador web, C es la menor de las prioridades. Nunca tuve una razón real para sumergirme profundamente en este lenguaje, a pesar de comprar innumerables cursos de Udemy y libros en C, nunca los toqué (mantén tu aspecto crítico para ti, tú también lo hiciste) o me mentí a mí mismo que si compro reloj inteligente Pebble, que funciona en C, luego asegúrese de escribir un código para ellos. Si, seguro! Ninguno de estos motivos fue lo suficientemente bueno.
¿Qué es WebAssembly y cómo supera a JS?
WebAssembly (Wasm para abreviar) es un formato de instrucciones binarias para una máquina virtual apilada.
"Wasm se desarrolló como una plataforma portátil para compilar lenguajes de alto nivel como C / C ++ / Rust, que le permite implementar aplicaciones de cliente y servidor en Internet"
- explica amablemente webassembly.org
En otras palabras, lo anterior significa que puede escribir módulos que funcionan en Internet en un navegador / servidor, pero que están escritos en lenguajes como C, compilados en un archivo binario y, por lo tanto, increíblemente rápidos porque funcionan directamente en el hardware de la máquina. En comparación, los lenguajes de script como JavaScript tienen varios niveles de abstracción entre el código y el hardware, lo que, entre otras cosas, los hace lentos. Por supuesto, esto no siempre importa, y cada uno de ellos tiene su propio lugar en el programa o incluso en el ecosistema web.
En base a esto, Wasm by structure (inicialmente) solo admite números enteros y números de punto flotante, lo que brinda una gran potencia informática y, por lo tanto, a menudo se usa para implementaciones de tipo canvas. Es importante comprender que WebAssembly no es una amenaza para JavaScript, al menos no todavía, y, como verá más adelante en este artículo, C y JavaScript pueden vivir muy felizmente en el mismo proyecto y pueden ejecutar el código del otro. Sí, algo por el estilo.
Emscripten "pegamentos" C y JS
Ahora espera! Sé lo que digo. No puede decir cosas como "ejecutar C en JS y viceversa" y esperar que el mundo no reaccione. No importa cuán extraño suene, no estoy engañando. Resulta que Emscripten es una cadena de herramientas para compilar en asm.js y WebAssembly, diseñado usando LLVM (Dios mío, aprendí la mitad de estas cosas mientras escribía el texto del artículo), lo que le permite ejecutar C y C ++ en Internet a una velocidad casi nativa sin complementos.
Bueno, esto es lo que necesitas destacar de esto para ti. Emscripten lo ayuda a compilar el código C en WebAssembly, proporcionando herramientas adicionales para facilitar la carga del desarrollador cuando se trata de comunicarse entre los dos idiomas, y le ayuda a iniciar Wasm en su proyecto web. El comando de compilación básico para Emscripten es el siguiente:
emcc lib/strings.c -s WASM=1 -o public/strings.js
Mientras que un comando no básico se ejecuta así:
emcc lib/imports.c -s WASM=1 -s EXPORTED_FUNCTIONS="['_getNum', '_main', '_getDoubleNum', '_greet']" -o public/imports.js
Configurar Emscripten no es lo más fácil, pero no lanzar un cohete. Lo único que complica la configuración es que tiene muchas dependencias como Python, Node, xCode, Git y cMake. Todas las instrucciones se pueden encontrar en la página de instalación y son fáciles de seguir.
Por lo tanto, Emscripten:
- es una gran herramienta para portar, que le permite compilar proyectos existentes escritos en C o C ++ y ejecutarlos en todos los navegadores modernos. ¡Sal de aquí, Internet Explorer!
- ideal para API porque convierte OpenGL a WebGL y le permite usar API familiares como SDL o directamente HTML5. Oh si!
- Y es muy rápido: gracias a LLVM, Emscripten, asm.js y WebAssembly, el código se ejecuta a casi su propia velocidad. ¡Corre, conejo, corre!
Nota: No necesita Emscripten para generar Wasm, ya que todos los navegadores nuevos tienen una API para admitir Wasm en la misma ventana, que ejecuta Emscripten como la capa superior, lo que facilita mucho la vida del desarrollador. Por ejemplo, Emscripten ajustará la cantidad de memoria para usted, que puede ser tediosa a través de C.
Ejemplos ... ejemplos están en todas partes!
Como dicen, "una línea de código vale más que mil palabras" , esta es una prerrogativa del narrador y todo eso, así que sin más preámbulos, echemos un vistazo a un código real. Comentario fuera del tema: ese día no pude superar la sintaxis de C. No se compiló la mitad del tiempo, porque mi código sería inestable. Y después de ocho años, estoy así: "Sí, parece JavaScript" .
Chicos, si alguien comienza a ver el código C en mi React, solo tráiganme de vuelta a la realidad, ¿de acuerdo?
Un poco fuera de tema, aquí está el código C actual:

Y, en consecuencia, en JavaScript:

OK, ¿qué sucede exactamente en estos archivos? En realidad bastante, así que lo enumeraré.
- Es importante comprender que main () , a menos que se especifique lo contrario, siempre comienza primero y también se compila de manera predeterminada. Si desea compilar otra función, deberá establecerla específicamente en el indicador de la matriz EXPORTED_FUNCTIONS , como se muestra en la sección anterior.
- Escribes tu código C, como de costumbre, importando sus bibliotecas regulares, pero además obtienes azúcar sintáctico Emscripten, así como más métodos / funciones que con cualquier otra herramienta.
- El archivo imports.js (el nombre es arbitrario, pero siempre el mismo que el archivo C) al que hace referencia HTML no es más que el "pegamento" Emscripten, que se genera automáticamente en la compilación. No necesita preocuparse por eso, solo asegúrese de que esté realmente referenciado.
- Printf es solo una instrucción C ordinaria que registra una cadena en la consola. Nada especial, sigue adelante.
- Las líneas 14 y 17 son un antipatrón, pero un buen ejemplo de ejecutar JS en su código C. La única diferencia real entre emscripten_run_script y emscripten_async_run_script es que este último le permite ejecutar JS en C de forma asíncrona. Principalmente con setTimeout () . La razón por la que dije que esto es un antipatrón es porque lo es. La idea general de WebAssembly es ejecutar C en JS, no JS en C, y por lo tanto ...
- Las líneas 20 y 24 y sus funciones JS asociadas en el archivo index.html representan la plantilla correcta, es decir, declarar su JS en su JS y devolver algo para C.
- EM_JS , que luego lanza jsFunction , es simplemente una forma más fácil: lograr el mismo objetivo que en los puntos 4 y 5.
El resultado previsto de lo anterior es el siguiente:

Señoras por delante!
Como con cualquier código, WebAssembly también tiene un orden de ejecución. ¡No te metas con la cola! El orden en este caso es estándar para el orden C. Todo comienza en Main () y siempre que main () esté listo, Wasm está listo. Sin embargo, ¿qué sucede si necesita una función estática para llamar en tiempo de ejecución? Bueno, solo un poco de azúcar sintáctica Emscripten, y todo funciona como un reloj:

Recolectamos moscas del pastel
Este es un código bien escrito, especialmente las cosas simples ilustradas en las secciones anteriores, pero todos sabemos que el mundo real es mucho más grande que el "Hola Mundo", y la mitad del tiempo de cada desarrollador se dedica a descubrir por qué el código no está haciendo lo que debería. Los errores son simplemente inevitables y, en cierto sentido, son parte de la vida.
Cuando ejecuta C en JS o cualquier Wasm, todo puede volverse aún más deprimente. Afortunadamente, Emscripten viene al rescate nuevamente al proporcionar dos métodos de depuración muy útiles:
// browser debugger gets triggered emscripten_debugger(); // browser console warning with stack-trace emscripten_log(EM_LOG_WARN, “'param' your message”);
Quick Gonzalez se apresura a ayudar
Lo creas o no, los creadores de Emscripten han pensado en todo. Una gran característica, y la última que mencionaré en este artículo, ya que hay demasiados para ponerlos en uno, es la base para un rápido desarrollo y pruebas. Puede compilar su Wasm, construir un proyecto e iniciar el servidor de una sola vez:
emrun --port 7777 --no_browser public/index.html Now listening at http://localhost:7777/
La página html que está ejecutando no es compatible con emrun. La captura de Stdout, stderr y exit (código de retorno) no funcionará. Vuelva a compilar la aplicación con el indicador de enlace --emrun para habilitar esto, o pase --no_emrun_detect a emrun para ocultar esta verificación.
De acuerdo, en dos personas ... el ejemplo anterior funciona, pero el siguiente funciona mejor, lo que explica el error que se muestra.
<b>// compile as emrun project emcc lib/strings.c -s WASM=1 --emrun -o public/index.html // run the emrun server again emrun --port 7777 --no_browser public/index.html</b>
Solo lo dejo así. Estudiando WebAssembly, celebré el día de San Patricio y al día siguiente. No estoy muy seguro de lo que sucederá después, pero me emocionó lo suficiente como para sentarme frente al monitor durante dos días, tratando de entrar en los conceptos básicos de WebAssebly, y eso debería significar algo, ¿verdad? Este es el código C que he escrito desde 2011, y se siente genial. Creo que WebAssembly tiene un futuro real, pero no estoy seguro de si se hará cargo completamente de la red y matará a JS, como algunos predican. Que piensas
