Closures en C y Objective-C

junio 30, 2010

Si, aunque intenteis leer otra vez el título del post, vamos a hablar de, las tan de moda, closures para C. 🙂

Sin duda, dada la naturaleza de C, se hace extraño que se añadan funcionalidades que normalmente se asocian a lenguajes mas modernos (o aún en evolución) como C#, Java o otros lenguajes de script como Python o Ruby

El nombre elegido para referirnos es “blocks”, y básicamente ha sido un añadido de Apple al compilador GCC que usamos en Mac y al futuro CLang que corre sobre el también futuro y prometedor LLVM.

Por el momento esta extensión de C no es estandar, y dada la cerrada naturaleza de los estándares de C es complicado que llegue a serlo. Pero, por otro lado, al estar implementado en compiladores como GCC o en el frontend de LLVM Clang, y además, al ser estos compiladores opensource y portables entre diferentes plataformas, presumiblemente esta extensión se pueda utilizar sin problemas en el futuro, al igual que usamos ciertas extensiones propias de GCC que tampoco forman parte de los estandares de C.

Apple desarrolló los blocks como parte de la tecnologia “Grand Central Dispatch”. Esta tecnologia optimiza ciertos bloques de ejecución, y como podeis esperar, el “empaquetar” los bloques de ejecución usando esta extensión del lenguaje facilita mucho la gestión por parte del sistema operativo y la programación por parte de los desarrolladores.

Hasta ahora hemos estado hablando alegremente de closures, básicamente los closures es una forma de encapsular un comportamiento bajo una variable. Usando esta variable podemos manejar el comportamiento (o función) de la misma manera que manejamos el resto de variables, esto es, por ejemplo, pasarlo como parámetros a una función.

Como siempre, lo mejor es verlo con un ejemplo, antes de adentrarnos en C,vamos a ver un ejemplo en Javascript. Lo bueno de este lenguaje es que la sintaxis es muy sencilla y nos va a permitir ver el concepto mas fácilmente.

funcion_suma = function(a,b) { return a+b; }
funcion_resta = function(a,b) { return a-b; }

function opera(op1, op2, operacion) {
	return operacion(op1, op2);
}

opera(3, 2, funcion_suma);
  // Imprime 5
opera(3, 2, funcion_resta);
  // Imprime 1
opera(3, 2, function(a,b) {
	return a*b;
});
  // Imprime 6

En el ejemplo creamos dos variables asignadas a funciones, que realizan las diferentes operaciones, y estas variables se las pasamos a la funcion “opera”. Cuando desarrollamos la funcion “opera” no sabemos que operación vamos a realizar, dejamos esa puerta abierta para que cada cliente de la función aporte su propia función de operación. Como vemos en el último caso, podemos definir la propia función cuando construimos los parámetros de la llamada.

La gran ventaja de esta técnica es la extensibilidad, ya que dejamos total libertad para que el desarrollador aporte la función a la que se va a llamar. Este ejemplo es muy sencillo, pero al final del post veremos puntos de Cocoa donde se estan usando los blocks y veremos de forma mas clara en que son una ventaja.

Centrandonos ya en C, Apple ha escogido el simbolo ^ para marcar un bloque. Es curioso ya que este simbolo se utilizaba en otra extension de C++ por parte de Microsoft para marcar cierto tipo de variables cuando se desarrolla con Managed C++.

Por lo tanto, para definir un bloque en C, usamos el simbolo ^, seguido de la lista de parámetros entre parentesis y después el bloque de codigo que conforma el bloque. Para definir el tipo del bloque usamos el tipo de retorno, el nombre del bloque entre parentesis y precedido de ^ y finalmente la lista de parámetros entre parentesis. Aunque pensandolo bien todo este parrafo me lo podría haber ahorrado, simplemente poniendo un ejemplo 😉

int (^funcion_suma)(int, int) = ^(int a, int b) { return a + b; };

Siguiendo la linea anterior, esta sería la forma de declarar una variable de tipo “funcion_suma” al igual que haciamos en javascript. Como vemos, la sintaxis es realmente mas compleja que la de javascript.

int opera(int op1, int op2, int (^funcion_opera)(int, int)) { return funcion_opera(op1, op2); }

opera(3, 2, funcion_suma);
  // Imprime 5
opera(3, 2, ^(int a, int b) {
	return a * b;
})
  // Imprime 6

Y aquí tenemos la anterior versión de la función “opera” pero en C, como vemos el concepto es similar, pero con una sintaxis mas enrevesada.

Si habeis programado en otros lenguajes como Java, la ultima invocación os sonara a clases anonimas, y ciertamente se les parece bastante. Al igual que con estas clases los blocks tienen suelen ser un buen sustituto a la hora de crear un callback. Una ventaja con respecto a la forma tradicional de implementar dichos mecanismos, es que pueden acceder a las variables locales del entorno donde se estan ejecutando. Esto es bastante util en numerosas ocasiones, usando blocks nos ahorraremos tener que pasar dichos datos a la funcion u objeto que implemente el callback.

Para marcar que una variable va a ser accedida dentro de un bloque, usamos el modificador __block antes de la variable que va a ser accedida dentro del bloque. Como por ejemplo:


__block int multiplicador = 6;

opera(3, 2, ^(int a, int b) {
	return a * b * multiplicador;
})
  // Imprime 36;

A partir de iOS 4 en el iPhone y OSX 10.6 los bloques son una realidad en Cocoa y Cocoa Touch. Poco a poco van apareciendo métodos que soportan un bloque para indicar el comportamiento de una acción.

Un ejemplo, sacado de la documentación de apple es método sortedArrayUsingComparator: del NSArray. El uso tradicional de este funcionalidad seria pasandole un puntero a función que resuelva la comparación, como podemos ver en sortedArrayUsingFunction:context:. Como hemos visto anteriormente, dada a la limitación de este método, Cocoa nos proporciona un puntero a nuestros datos, reflejado en el parámetro context.

Si usamos bloques en este caso, nos saltamos esta limitación, y además, facilita la lectura del código ya que podemos poner la lógica del comparador en la misma llamada de la función.

Para finalizar el post, vamos a ver un ejemplo de una ordenación de un Array usando bloques y sin usarlos

Usando el método tradicional, la ordenación del array quedaría algo como:

NSInteger alphaComparator(id arg1, id arg2, void* arg3) {
  NSString *a = (NSString*)arg1;
  NSString *b = (NSString*)arg2;
  return strcmp([a cStringUsingEncoding:[NSString defaultCStringEncoding]],
				[b cStringUsingEncoding:[NSString defaultCStringEncoding]]);
}

int main (int argc, const char * argv[]) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  NSArray *stringsArray = [NSArray arrayWithObjects:
    @"Roberto",
	@"Alfonso",
	@"Ruben",
	@"Mariano",
    @"Juan",
	@"Antonio",nil];

  NSArray* sortedArray = [stringsArray
			sortedArrayUsingFunction:alphaComparator context:nil];
  for ( NSString* cad in sortedArray ) {
    NSLog(@"%@\n", cad);
  }

  return 0;
}

Por otro lado, usando bloques quedaría algo como:

iint main (int argc, const char * argv[]) {

  NSArray *stringsArray = [NSArray arrayWithObjects:
   @"Roberto",
   @"Alfonso",
   @"Ruben",
   @"Mariano",
   @"Juan",
   @"Antonio",nil];

  NSArray* sortedArray = [stringsArray sortedArrayUsingComparator:^(id str1, id str2) {
    NSString *a = (NSString*)str1;
	NSString *b = (NSString*)str2;
	return (NSComparisonResult)
			strcmp([a cStringUsingEncoding:[NSString defaultCStringEncoding]],
				  [b cStringUsingEncoding:[NSString defaultCStringEncoding]]);
  }];

  for ( NSString* cad in sortedArray ) {
	NSLog(@"%@\n", cad);
  }

  return 0;
}

Sin duda, bajo mi punto de vista la solución usando bloques es mucho mas elegante, pese a que el enfrentamiento inicial con los blocks pueda ser algo “dura” 😀

Como conclusión, simplemente decir que es muy grato ver como se van añadiendo funcionalidades a nuestro lenguaje favorito y, de esta manera, adaptandolo un poco mas a los tiempos en los que vivimos 🙂


Más vale tarde que nunca. Extensiones en Safari.

junio 14, 2010

Pese a que toda la atención del WWDC se la ha llevado el nuevo iPhone, entre el barullo del nuevo teléfono de Apple se ha lanzado una nueva versión del navegador por defecto del OSX, estamos hablando de Safari 5.

Una de las grandes novedades del Safari 5 es que incorpora la posibilidad de ejecutar extensiones, de la misma manera que hace Firefox desde hace mucho tiempo, o mas recientemente Chrome, de hecho, el concepto utilizado es muy similar al usado en el navegador de Google.

Además de para OSX, Safari 5 también esta disponible para Windows, y a diferencia de las versiones anteriores y, basado en mis escasas pruebas, parece que es cuanto menos usable. La buena noticia es que las extensiones son totalmente funcionales también en el sistema operativo de Microsoft.

Hablando ya de las extensiones de Safari, existen varios tipos. Si hablamos de modificar o añadir elementos a la interfaz gráfica de Safari, podemos tener nuevos botones, nuevas barras o nuevos elementos que se añadirán al menú contextual. Aparte de estos elementos, podremos tener extensiones que modifiquen la propia web que estamos visitando, como el típico bloqueador de anuncios o de contenidos Flash

Desde el punto de vista técnico, las extensiones estan programadas usando las típicas técnologias web; HTML5, CSS3 y Javascript

Entrando un poco mas en detalle, típicamente las extensiones estarán formadas por una página HTML que se cargará al incio de la extensión. Esta página la usaremos para colocar las inicializaciones del resto de componentes, así como los eventos que responderán a los elementos gráficos de la propia extension.

Además de esta pagina web, tendremos según los requisitos de esta extension, un conjunto de HTML y CSS que controlarán el aspecto gráfico de nuestra extensión. Por ejemplo, si queremos hacer una barra que muestre algun tipo de información, dicha información estará descrita por un fichero HTML con su correspondiente hoja de estilo, imágenes e iconos.

Si, por otro lado, queremos que nuestra extensión modifique el contenido de la web, necesitaremos tener un conjunto de scripts programados usando Javascript, con el que grácias a la API que nos proporciona el navegador (ofrecida en Javascript tambíen), podremos acceder e incluso modificar el propio contenido de la web que se esta mostrando en el navegador.

Si queremos ponernos manos a la obra, el propio Safari tiene un editor para crear las extensiones. No esperar encontraros un editor de HTML ni nada parecido, en lo que nos ayudará sera en crear la estructura o el “paquete” en el que podremos meter los contenidos de las propias extensiones. Con el Extension builder podremos crear los botones, barras o scripts de las que hemos hablado anteriormente.

Para activarlo, necesitamos ir al menú de preferencias de Safari, y activar el menu de Desarrollador, que por defecto esta desactivado. Una vez activado dicho menú, podremos acceder al Extension builder

El último elemento que necesitamos para crear la extensión es un certificado de desarrollador. Sin este cerficado no podremos ni siquiera instalar una extensión en nuestro navegador. Como vemos, el concepto es muy similar al seguido con el iPhone.

La principal diferencia, es que formar parte del programa de desarrolladores de extensiones de Safari es totalmente gratis. Lo único que tenemos hacer es ir a la web de desarrolladores de apple, http://developer.apple.com y darnos de alta.

Después de rellenar los datos oportunos sólo tendremos que instalar el certificado en el llavero de Mac, o en el almacen de certificados de Windows, para que el Extension Builder lo detecte y nos deje instalar y empaquetar nuestra extensión


Medidor de luz en Cocoa usando Arduino

junio 8, 2010

Hace tiempo que no publicaba nada del magnífico Arduino. La culpa, como siempre, de que los días sólo tengan 24 horas 😉

En el anterior post sobre Arduino, presentamos lo fácil que era conectar processing con Arduino. En este post vamos a ver que no sólo con Processing, realmente leer los datos que nos da el Arduino es fácil desde cualquier sitio.

Para presentarlo vamos a mostrar un pequeño programa hecho en Cocoa que lee los datos recogidos por el Arduino y lo muestra gráficamente.

En primer lugar pondremos el esquema del circuito.

El circuito es bastante sencillo y sin muchos secretos, el único detalle a tener en cuenta es que utilizamos una resistencia pull-up de 1KOhm para medir la tensión después del sensor LDR. Esto lo conectamos a la entrada 0 de la placa del Arduino.

De esta manera el arduino leerá el valor de esa entrada, pero necesitamos alguna manera para comunicarnos con el PC. Aquí es donde entra la sencillez del Arduino, ya que podemos usar el puerto USB para comunicarnos. Los datos los enviaremos con la librería Serial. Desde el PC, al tratarse de una comunicación serie, podemos usar cualquier mecanismo para leer del puerto. Y cuando decimos cualquiera, realmente hay un mundo de posibilidades, por mencionar algunos, tenemos librerias en Python, Java o incluso usando la librería estandar de C.

El código del programa que cargamos en el arduino es el siguiente

int LDR = 0;
int val = 0;
int delayTime = 500;

void setup()
{
  pinMode(LDR, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  val = analogRead(LDR);
  Serial.println(val);
  val = 0;
  delay(delayTime);
}

Como vemos es bastante sencillo. En el Setup, configuramos el puerto serie con una velocidad de 9600 baudios y cada lectura la escribimos en el puerto serie usando el Serial.write.

De la misma manera podemos usar el puerto USB para establecer la comunicación inversa, en algun futuro post veremos como realizarla, y como usar el Arduino como medio para mostrar información de forma diferente.

Cuando instalamos el driver de Arduino en nuestro PC, nos crea un dispositivo que variará segun el sistema operativo. En mi caso, OSX, el dispositivo es /dev/tty.usbserial-A900aeKy , por lo que con el programa cargado, podremos leer de ese puerto los datos que esta leyendo la placa del sensor. Para ello podemos usar el programa screen, que viene con la gran mayoría de sistemas basados en UNIX.

Si ejecutamos en una terminal el comando

$ screen /dev/tty.usbserial-A900aeKy

Deberíamos ver algo parecido a esto:

En pantalla podemos ver como van apareciendo los valores que esta leyendo la placa, si variamos la intensidad de la luz, efectivamente vemos como dichos valores cambian.

Una vez que tenemos lista la parte del Arduino, la siguiente parte es crear la aplicación en PC. Como hemos mencionado antes, para capturar los datos que nos llegan, debemos leer del puerto serie. Para ello, y al estar en un sistema Unix, podemos utilizar la Api estándar para leer de un dispositivo.

Como esto lo vamos a usar desde una aplicación en Cocoa, vamos a encapsular estas funciones en un objeto de cocoa, de tal manera que su uso sea mas sencillo. Este objeto al construirse abrirá el puerto serie, y nos ofrecerá un método para obtener el siguiente valor leído.

Hablando del código en C, como podeis suponer no tiene mucho secreto, usando open() abriremos el fichero que representa el dispositivo, y con read() leeremos los datos.

El enlace al código fuente esta al final de la entrada, pero el código principal que realiza esto es algo como lo siguiente:

int fd = open("/dev/tty.usbserial-A900aeKy", O_RDWR | O_NOCTTY | O_NDELAY);
char buffer[100]; memset(buffer, 0, 100);
int nbytes = read(fd, buffer, 100);

La última parte que nos falta del puzzle es la aplicación Cocoa que se encargará de mostrar los datos, la idea es mostrar un numero que indique el valor leido del sensor, y un medidor del tipo NSLevelIndicator para mostrar un indicador gráfico del valor del sensor.

No entraré en detalle en comentar la aplicación en Cocoa ya que es muy sencilla, la aplicación consta de una Custom View que pinta el número leido. Para realizar las lecturas periodicas, se utiliza un NSTimer que llamará periodicamente a un método que le especifiquemos y que se encargará de actualizar la vista con el nuevo dato leido.

Para finalizar el post, os dejo con un video del programa en funcionamiento y el código de la aplicacion Cocoa y del programa de Arduino.

Codigo Fuente