NaCl: El Silverlight/Flash de Google? - WarNov Developer Evangelist - Site Home - MSDN Blogs

NaCl: El Silverlight/Flash de Google?

NaCl: El Silverlight/Flash de Google?

Rate This
  • Comments 9

En mi continuo transitar por las novedades tecnológicas (no sé a que hora visito tanto sitio…) Me encontré con que Google de una manera bastante discreta estaba lanzando una tecnología abreviada como la sal: NaCl. Acrónimo de Native Client.

NaCl = Sal

Native Client es una idea supernovedosa

Con la cual de acuerdo a lo que encontramos en el sitio del proyecto, tenemos un fabuloso SDK que permitirá al browser ejecutar código nativo para construir aplicaciones web de alta respuesta e interactividad… (no les suena esto familiar?)

Lo cual, me parece bastante curioso, dado todo lo que Google ha dicho acerca de su firme apoyo a HTML 5, que pretende solucionar el mismo tipo de problema.

Dijo el vice presidente de ingeniería Vic Gundotra en el Google I/O de 2009: “HTML 5, will be the future of the web”.

Y si es así? Para qué desgastarse tratando de implementar toda una tecnología para correr código nativo desde el browser? Sobretodo cuando se ha criticado al mismo tipo de tecnologías ya implementadas como Silverlight y Flash?

Será que en el fondo no creen mucho en HTML5? O será que en el fondo creen mucho en tecnologías Silverlifght/Flash?

NaCl tiene un SDK que funciona en Windows, Linux y Mac… Genial! Y lo mejor de todo, es que las aplicaciones las programaríamos en una suerte de sancocho (léase mescolanza o MIX para los más modernos) de CSS, HTML, Javascript y sí, el amigable C/C++! Todo para lograr que la aplicación no se vea como un frame embebido dentro del HTML, sino como puro HTML.

Este C/C++ nos permitirá crear de una forma bastante sencilla gráficos en 2D/3D, ejecutar audio y responder a eventos del mouse y teclado!

Pero…

Cuál es el AS bajo la manga de Google que aventajará a Silverlight y Flash?

Pues que no se requerirá plugin! No habrá que instalar nada!!!
Bueno, excepto el propio browser de Google (Chromium). Entonces ha de ser que para ellos no existen más browsers :

“all without requiring users to install a plugin. These web apps run in recent versions of Chromium with the --enable-nacl flag.”

Bueno; pero pongamos esas des-virtudes a un lado y démosle una oportunidad de prueba; observemos cómo sería la programación. Primero, veamos cómo sería la página web que hospedaría la sal; digo, NaCl:

   1:  <!DOCTYPE html>
   2:  <html>
   3:    <!--
   4:    Copyright (c) 2010 The Native Client Authors. All rights reserved.
   5:    Use of this source code is governed by a BSD-style license that can be
   6:    found in the LICENSE file.
   7:    -->
   8:  <head>
   9:    <title>Hello, World!</title>
  10:   
  11:    <script type="text/javascript">
  12:      hello_world = null;  // Global application object.
  13:      status_text = 'NO-STATUS';
  14:   
  15:      function moduleDidLoad() {
  16:        hello_world = document.getElementById('hello_world');
  17:        updateStatus('SUCCESS');
  18:      }
  19:   
  20:      // If the page loads before the Native Client module loads, then set the
  21:      // status message indicating that the module is still loading.  Otherwise,
  22:      // do not change the status message.
  23:      function pageDidLoad() {
  24:        if (hello_world == null) {
  25:          updateStatus('LOADING...');
  26:        } else {
  27:          // It's possible that the Native Client module onload event fired
  28:          // before the page's onload event.  In this case, the status message
  29:          // will reflect 'SUCCESS', but won't be displayed.  This call will
  30:          // display the current message.
  31:          updateStatus();
  32:        }
  33:      }
  34:   
  35:      function fortytwo() {
  36:        try {
  37:          alert(hello_world.fortytwo());
  38:        } catch(e) {
  39:          alert(e.message);
  40:        }
  41:      }
  42:   
  43:      function helloworld() {
  44:        try {
  45:          alert(hello_world.helloworld());
  46:        } catch(e) {
  47:          alert(e.message);
  48:        }
  49:      }
  50:   
  51:      // Set the global status message.  If the element with id 'status_field'
  52:      // exists, then set its HTML to the status message as well.
  53:      // opt_message The message test.  If this is null or undefined, then
  54:      //     attempt to set the element with id 'status_field' to the value of
  55:      //     |status_text|.
  56:      function updateStatus(opt_message) {
  57:        if (opt_message)
  58:          status_text = opt_message;
  59:        var status_field = document.getElementById('status_field');
  60:        if (status_field) {
  61:          status_field.innerHTML = status_text;
  62:        }
  63:      }
  64:    </script>
  65:  </head>
  66:  <body onload="pageDidLoad()">
  67:   
  68:  <h1>Native Client Simple Module</h1>
  69:  <p>
  70:    <button onclick="fortytwo()">Call fortytwo()</button>
  71:    <button onclick="helloworld()">Call helloworld()</button>
  72:   
  73:    <!-- For development, use a #develop location, which loads the develop
  74:    version of the module.
  75:    -->
  76:    <div id="nacl_helloworld_content"></div>
  77:    <script type="text/javascript">
  78:      contentDiv = document.getElementById('nacl_helloworld_content');
  79:      if (window.location.hash == '#develop') {
  80:        // Load the develop version of the module.
  81:        contentDiv.innerHTML = '<embed name="nacl_module" '
  82:                               + 'id="hello_world" '
  83:                               + 'width=0 height=0 '
  84:                               + 'type="pepper-application/hello_world" />';
  85:        moduleDidLoad();
  86:      } else {
  87:        // Load the published .nexe.  This includes the 'nexes' attribute which
  88:        // shows how to load multi-architecture modules.  The relative URLs in
  89:        // the following table should be matched with a similar directory
  90:        // structure on your server.
  91:        var nexes = 'x86-32: hello_world.nacl/x86_32/hello_world.nexe; '
  92:                    + 'x86-64: hello_world.nacl/x86_64/hello_world.nexe; '
  93:                    + 'ARM: hello_world.nacl/arm/hello_world.nexe; ';
  94:        contentDiv.innerHTML = '<embed name="nacl_module" '
  95:                               + 'id="hello_world" '
  96:                               + 'width=0 height=0 '
  97:                               + 'src="hello_world.nexe" '
  98:                               + nexes
  99:                               + 'type="application/x-nacl-srpc" '
 100:                               + 'onload=moduleDidLoad() />';
 101:      }
 102:    </script>
 103:  </p>
 104:   
 105:  <p>If the module is working correctly, a click on the "Call fortytwo" button
 106:    should open a popup dialog containing <b>42</b> as value.</p>
 107:   
 108:  <p> Clicking on the "Call helloworld" button
 109:    should open a popup dialog containing <b>hello, world</b> as value.</p>
 110:   
 111:  <h2>Status</h2>
 112:  <div id="status_field">NO-STATUS</div>
 113:  </body>
 114:  </html>

Bastante código para un Hello World no?

Independientemente de eso, observemos la estructura. Básicamente se trata de una página web convencional, cuyo DOM es manejado por un Javascript que accede a un objeto embebido (finalmente si se embeben objetos) que es precísamente el gestor de NaCl, el cual carga archivos binarios de tipo “.nexe” escritos en C++ (Entonces lo que uno hace es indicar la ruta de dicho .nexe; muy parecido a Flash o Silverlight, donde uno indica la ruta del .xap). Hasta aquí noto algunas desventajas con Silverlight… por ejemplo, no se sabe si la página carga antes o después del NaCl; así que hay que escribir lógica adicional para cuando esto sucede. También tenemos que estar mezclando en todo lado Javascript, para traer los datos desde el NaCl al DOM de la página. Finalmente siempre tienen que diferenciarse las versiones de desarrollo de las de producción. En Silverlight, no hay tal diferenciación. Sin embargo, he de decir, que no son diferencias tan graves y que en el fondo el funcionamiento es muy similar, en cuanto a la idea como tal.

Pero ahora veamos, cómo se programa la parte nativa de la aplicación.

Como ya les había comentado, usamos el poderoso y amigable C/C++ para dicha programación.

Luego de muchos tropiezos, por fin logré sacar el código que me daría un mensaje de texto que diría Hello World, el cual se transfiere a la página a través de Javascript y se muestra en un ‘alert´.

Veamos el código:

   1:  // Copyright 2008 The Native Client Authors. All rights reserved.
   2:  // Use of this source code is governed by a BSD-style license that can
   3:  // be found in the LICENSE file.
   4:   
   5:  #include <stdbool.h>
   6:  #include <stdio.h>
   7:  #include <stdlib.h>
   8:  #include <string.h>
   9:   
  10:  #if defined(__native_client__)
  11:  #include <nacl/nacl_npapi.h>
  12:  #else
  13:  // Building a develop version for debugging.
  14:  #include "third_party/npapi/bindings/npapi.h"
  15:  #include "third_party/npapi/bindings/nphostapi.h"
  16:  #endif
  17:   
  18:  // These are the method names as JavaScript sees them.
  19:  static const char* kHelloWorldMethodId = "helloworld";
  20:   
  21:  // This function creates a string in the browser's memory pool and then returns
  22:  // a variable containing a pointer to that string.  The variable is later
  23:  // returned back to the browser by the Invoke() function that called this.
  24:  static bool HelloWorld(NPVariant *result) {
  25:    if (result) {
  26:      const char *msg = "hello, world.";
  27:      const int msg_length = strlen(msg) + 1;
  28:      // Note: |msg_copy| will be freed later on by the browser, so it needs to
  29:      // be allocated here with NPN_MemAlloc().
  30:      char *msg_copy = reinterpret_cast<char*>(NPN_MemAlloc(msg_length));
  31:      strncpy(msg_copy, msg, msg_length);
  32:      STRINGN_TO_NPVARIANT(msg_copy, msg_length - 1, *result);
  33:    }
  34:    return true;
  35:  }
  36:   
  37:  static NPObject* Allocate(NPP npp, NPClass* npclass) {
  38:    return new NPObject;
  39:  }
  40:   
  41:  static void Deallocate(NPObject* object) {
  42:    delete object;
  43:  }
  44:   
  45:  // Return |true| if |method_name| is a recognized method.
  46:  static bool HasMethod(NPObject* obj, NPIdentifier method_name) {
  47:    char *name = NPN_UTF8FromIdentifier(method_name);
  48:    bool is_method = false;
  49:    if (!strcmp((const char *)name, kHelloWorldMethodId)) {
  50:      is_method = true;
  51:    } else if (!strcmp((const char*)name, kFortyTwoMethodId)) {
  52:      is_method = true;
  53:    }
  54:    NPN_MemFree(name);
  55:    return is_method;
  56:  }
  57:   
  58:  static bool InvokeDefault(NPObject *obj, const NPVariant *args,
  59:                            uint32_t argCount, NPVariant *result) {
  60:    if (result) {
  61:      NULL_TO_NPVARIANT(*result);
  62:    }
  63:    return true;
  64:  }
  65:   
  66:  // Invoke() is called by the browser to invoke a function object whose name
  67:  // is |method_name|.
  68:  static bool Invoke(NPObject* obj,
  69:                     NPIdentifier method_name,
  70:                     const NPVariant *args,
  71:                     uint32_t arg_count,
  72:                     NPVariant *result) {
  73:    NULL_TO_NPVARIANT(*result);
  74:    char *name = NPN_UTF8FromIdentifier(method_name);
  75:    if (name == NULL)
  76:      return false;
  77:    bool rval = false;
  78:   
  79:    // Map the method name to a function call.  |result| is filled in by the
  80:    // called function, then gets returned to the browser when Invoke() returns.
  81:    if (!strcmp((const char *)name, kHelloWorldMethodId)) {
  82:      rval = HelloWorld(result);
  83:    } else if (!strcmp((const char*)name, kFortyTwoMethodId)) {
  84:      rval = FortyTwo(result);
  85:    }
  86:    // Since name was allocated above by NPN_UTF8FromIdentifier,
  87:    // it needs to be freed here.
  88:    NPN_MemFree(name);
  89:    return rval;
  90:  }
  91:   
  92:  // The class structure that gets passed back to the browser.  This structure
  93:  // provides funtion pointers that the browser calls.
  94:  static NPClass kHelloWorldClass = {
  95:    NP_CLASS_STRUCT_VERSION,
  96:    Allocate,
  97:    Deallocate,
  98:    NULL,  // Invalidate is not implemented
  99:    HasMethod,
 100:    Invoke,
 101:    InvokeDefault,
 102:    NULL,  // HasProperty is not implemented
 103:    NULL,  // GetProperty is not implemented
 104:    NULL,  // SetProperty is not implemented
 105:  };
 106:   
 107:  NPClass *GetNPSimpleClass() {
 108:    return &kHelloWorldClass;
 109:  }

Cristalino no?

Y solo para un “Hello World!“


Ahora veamos lo mismo con Silverlight

   1:  using System;
   2:  using System.Windows;
   3:  using System.Windows.Controls;
   4:   
   5:   
   6:  namespace HelloSilverlight
   7:  {
   8:      public partial class MainPage : UserControl
   9:      {
  10:          public MainPage()
  11:          {
  12:              // Required to initialize variables
  13:              InitializeComponent();
  14:          }
  15:   
  16:          private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
  17:          {
  18:              MessageBox.Show("Hello World");
  19:          }
  20:      }
  21:  }

Bueno; el código habla por sí solo!!!

Por si fuera poco, observemos el tamaño del ejecutable que finalmente tiene que descargar el usuario:

NaCl:

image

Silverlight:

image

Hum… 1143 veces menor

Bueno; a favor de Google digamos que esta es la primera muestra en público de la plataforma y que todavía no está en producción. Pero que o recuerde, Silverlight en sus primeras apariciones no tenía esos inconvenientes.. yo creo que deberían refinar un poco más el producto a mostrar, antes de sacar su preview!

Por otro lado, también pienso que así evolucione mucho, (disminuir el tamaño final, simplificar la comunicación con el DOM, etc.) La programación como tal del cliente nativo no tendrá nada que hacer en cuanto a productividad si no se usa un lenguaje administrado.

Hoy en día los recursos de hardware que existen para la mayoría de las aplicaciones (yo diría un 96%) permiten que las ligeras ventajas en tiempo de ejecución logradas con lenguajes no administrados como C/C++ sean imperceptibles… así que vamos… cuál es el punto?

 

Leave a Comment
  • Please add 8 and 2 and type the answer here:
  • Post
  • interesante, pero el aspecto q he leido, es que el tamano es pq va embebido un 'pequeno' de-compilador ya que los navegadores aun no soportan html 5 y ese *.nexe es el plug q busca en los temporales para poderse visualizar, craso error pero es la razon q lei x ahi!!!

  • En realidad no Oscardo; NaCl no tiene que vefr con HTML5; son vertientes distintas. El *.nexe es como el .xap en silverlight. Es la aplicación que se ejecuta. En este caso en forma nativa. Por ejemplo si es en Windows, accede al API directamente. La ejecución la hace el sistema operativo directamente sin plugins, pero como vimos, es requerido el uso del browser propio de Google, así que no es mucha la ganancia...

  • Pues como Google ha estado sacando fails ultimamente, no me sorprenderia que este fuera uno más.

    Este asunto deberia ser tomado como algo experimental más que cualquier otra cosa, Google tiene ese habito experimental con las tecnologías por ejemplo hay otros plugins por ahi que no han hecho ruido como el O3D que supuestamente iba a ser un elemento importante para construir un nuevo tipo de aplicaciones web en "3D" y ahora tomó una nueva dirección (o mejor, naufrago) con el WebGL.

    Y pues es curioso ver que Google quiera ponerse a competir en el campo de los plugins, pero realmente no creo que sea justo compararlo con Silverlight que tecnologicamente esta a millones de años luz inclusive de Flash.

  • Coincido con David: otro #fail de Google.

  • Pues lo que se gana no pidiendo el plugin al cliente se pierde en eficacia entregarle al mismo una solución que se puede desarrollar rapidamente en Silverlight ó en su defecto en Flash

  • Jajaja Walter, pero si eso es puro y duro C++, nada más esos monstruosos punteros. Los .h me remontan a tiempos inolvidables, pero ya pasados de moda. Les falta realmente mucho para lograr llegar al estado de algo como silverlight, por ejemplo clonar a Anders Hejlsberg para que les haga un lenguaje de última generación que podrían llamar H2O. Pasa lo mismo que con GOOGLE Wave, se suponía que era el SharePoint online, al menos eso pensé, y fue catalogado como uno de las peores productos el año pasado creo, o este año, ya ni interesa. geeklad.com/5-reasons-google-wave-is-not-ready

  • Jajajajaj H2O... genial Andrés... tienes toda la razón

  • no me gusta, no me gusta, no me gusta.

    seguramente lo van a usar en el chrome OS, pero uno nunca sabe.

  • Si consiguen hacer un sandbox seguro, conectan on LLVM y lo hacen libre, os aseguro que pueden cambiar la web. Javascript es mucho mas eficiente ultimamente, pero como lenguaje deja mucho que desear.

    Por supuesto que el codigo de Hello World sera mas complicado. Pero no se trata de eso, sino de correr codigo nativo, lo que abre las puertas a muchisimos otros lenguajes, no solo C/C++.

    Y lo de que por tener mejor hardware ya no hay que programar en C/C++ no tiene ningun sentido. Hombre, 640KB eran suficientes para todo el mundo y la web seria mejor si todo el mundo usara IE6.

Page 1 of 1 (9 items)