Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Primeros pasos con Rust y WebAssembly

Primeros pasos con Rust y WebAssembly

Una introducción a WebAssembly y Rust. Presentado originalmente en el mozMeetup de Oct 2018, Lima Perú.

Avatar for Lupo Montero

Lupo Montero

October 17, 2018
Tweet

More Decks by Lupo Montero

Other Decks in Programming

Transcript

  1. Disclaimer Imágenes, inspiración y algunas ideas a continuación, han sido

    tomadas de varios recursos abiertos; en particular el blog https://hacks.mozilla.org/ y los posts y presentaciones de Lin Clark (@linclark).
  2. Qué es WebAssembly? “WebAssembly (abbreviated Wasm) is a binary instruction

    format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.” Fuente: https://webassembly.org/
  3. Qué es Rust? “Rust es un lenguaje de programación de

    sistemas extremadamente rápido, previene fallas de segmentación y garantiza la seguridad de los hilos de ejecución.” Fuente: https://www.rust-lang.org/es-ES/
  4. Instalar rust • # dependencias recomendadas sudo apt-get install pkg-config

    libssl-dev • # instala rust curl https://sh.rustup.rs -sSf | sh
  5. Rust toolchain y wasm como target • # configura toolchain

    nightly por defecto rustup default nightly • # añade wasm como target rustup target add wasm32-unknown-unknown \ --toolchain nightly Fuente: https://rustwasm.github.io/wasm-bindgen/whirlwind-tour/basic-usage.html
  6. Rust => Wasm (101) • # creamos un proyecto indicando

    que va a ser una librería cargo new --lib <name> • Modificamos el tipo de “crate” en Cargo.toml: [lib] crate-type = ["cdylib"]
  7. Compilemos nuestro programa # Esto debería crear un archivo wasm:

    # target/wasm32-unknown-unknown/debug/mozmeetup.wasm cargo build --target wasm32-unknown-unknown
  8. Invocando una función de Rust desde JavaScript fetch('target/wasm32-unknown-unknown/debug/mozmeetup.wasm') .then(resp =>

    resp.arrayBuffer()) .then(result => WebAssembly.instantiate(result)) .then(wasm => console.log(wasm.instance.exports.sum(2, 3)));
  9. Optimizando el archivo wasm con wasm-gc cargo install wasm-gc #

    post-procesamos con wasm-gc... wasm-gc \ target/wasm32-unknown-unknown/debug/mozmeetup.wasm \ mozmeetup.gc.wasm
  10. Usando wasm optimizado con wasm-gc fetch('mozmeetup.gc.wasm') .then(resp => resp.arrayBuffer()) .then(result

    => WebAssembly.instantiate(result)) .then(wasm => console.log(wasm.instance.exports.sum(2, 3)));
  11. Pasando funciones de JavaScript a Rust Promise<ResultObject> WebAssembly.instantiateStreaming(source, options); const

    options = { env: { printToDOM: msg => document.body.appendChild(document.createTextNode(msg)), }, };
  12. Usando funciones de JavaScript en Rust extern { fn printToDOM(x:

    u32); } #[no_mangle] pub fn run() { unsafe { printToDOM(42); } }
  13. Y si necesitamos pasar más que números entre Rust y

    JavaScript? extern { fn printToDOM(x: String); } #[no_mangle] pub fn run() { unsafe { printToDOM(String::from("OMG")); } }
  14. src/lib.rs extern crate wasm_bindgen; use wasm_bindgen::prelude::*; #[wasm_bindgen(module = "../printToDOM")] extern

    { fn printToDOM(x: String); } #[wasm_bindgen] pub fn run() { printToDOM(String::from("OMG")); } #[wasm_bindgen] pub fn sum(a: u32, b: u32) -> u32 { a + b }
  15. Build y generación de bindings de JavaScript cargo build --target

    wasm32-unknown-unknown mkdir build wasm-bindgen \ target/wasm32-unknown-unknown/debug/mozmeetup.wasm \ --out-dir ./build
  16. Configuración de Webpack const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = {

    entry: './index.js', plugins: [ new HtmlWebpackPlugin({ title: 'Getting started with WASM' }), ], };
  17. Usando nuestro módulo desde JavaScript // index.js import('./build/mozmeetup') .then(wasm =>

    wasm.run()) .catch(console.error); https://webpack.js.org/api/module-methods/#import-
  18. Arrancando nuestra aplicación... npx webpack-dev-server --mode development ... "scripts": {

    "start": "webpack-dev-server --mode development" }, ... yarn start