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ú.

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