MonoTouch: muy bonito pero una guarrería

Ayer estuve jugando un poco con MonoTouch, más que nada por curiosidad. Para los que no lo sepáis, es un IDE más una biblioteca que envuelve de forma conveniente todo el desarrollo para iOS, tanto iPhone como iPad y que permite a un programador de C# desarrollar para estas plataformas sin tener que aprender nada de Objective-C y demás zarandajas.

Es un decir, porque realmente no es más que un envoltorio fino a todo eso. Por lo tanto, si estás desarrollando para Windows o Silverlight, no esperes sentarte y ponerte a ello porque aparte de usar la sintaxis de C#, todo lo demás es iOS. Incluso se usa el IDE de xCode para crear los elementos gráficos y su interactuación, como son los outlets (propiedades) y las actions (los eventos).

La ventaja es que al ser una capa fina apenas introduce sobrecarga y todo es nativo. El inconvenientes es que tienes que aprenderte todas las idiosincrasias del iOS.

Y otra cosa que no me creo mucho es el tema de la compartición de código. No esperes tener el mismo código fuente de tu aplicación y compilar para Android, iOS, OS X y Windows. Podrás compartir bloques de código, pero nada más.

***

Otra cosa es que estas herramientas son de pago. Desde 400$ la más barata hasta viarios miles de dólares. Depende de qué quieras y cómo. Las versiones gratuitas para Android e iOS no caducan pero sólo permiten ejecutar código en el simulador.

Las versiones para escritorio son completamente gratuitas.

Se me olvidaba decir 

***

Ahora bien, como decidas desinstalar algo… arreglado vas. Aparte de que no hay desinstalador, los procesos para hacerlo son completamente insuficientes y te dejan el sistema hecho unos zorros con miles de archivos desperdigados por todo el disco. 

Versiones anteriores traían un desinstalador embebido dentro del PKG que realizaba la instalación, pero al menos la que yo he instalado no lo trae.

Primero ejecuta los comandos descritos aquí. Eso te va a limpiar digamos que las partes públicas del entorno. Y si tienes la última versión de xCode instalada, te puedes cargar la carpeta /Developer de un plumazo sin problemas porque sólo tendrás el Mono de los cojones en ella. Pero antes de hacerlo, míralo por si acaso.

Una vez pasado ese script, si te pica la curiosidad, haz una búsqueda global con la palabra “mono”.

En mi caso he usado CleanMyMac para limpiar el ordenador de basura, pero tu puedes hacerlo a mano o con otra herramienta. Ojo con los ficheros que no son del mono.

Finalmente tenemos que desinstalar MonoDevelop. En mi caso, de nuevo con CleanMyMac.

Y creo, sólo creo, que tengo limpio de nuevo el sistema.

Hay que joderse.

C++/CX (IV). Clases parciales

Éramos pocos y parió la abuela. ¿Sabéis por qué C++/CLI (el C++ de .NET) se quedó en la cuneta en eso de ser a first class .NET language (o en cristiano: un lenguaje .NET de primera clase)? Efectivamente, la ausencia de clases parciales.

Cuando Microsoft introdujo el .NET 3.0 también cambió la forma de entender la interacción con la parte visual. Si bien antes las ventanas se construían con código, aunque de forma más o menos automatizada gracias al diseñador visual (hablamos de Windows Forms), a partir de ese momento se implementó una nueva forma que, pese a ser una idea cojonuda, peca un poco de mal implementada, como casi todo lo que hace la casa.

Los viejos lobos de mar nos hemos defendido con las plantillas de cuadro de diálogo, que definían los tales mediante una serie de palabras claves. Luego Windows se encargaba de leer la versión binaria de ese texto y nos construía nuestro cuadro de diálogo.

Pues bien, XAML es la enésima reencarnación de lo mismo, pero con esteroides. Y digo enésima porque por ejemplo Delphi, C++ Builder e incluso el ya vetusto VB6 lo hacían más o menos así.

XAML es un lenguaje (lo que me cuesta llamarlo así) XML que define la estructura de una ventana y todos sus componentes. La idea es tener algo que nos defina por completo, y de forma independiente del código, la parte visual de un programa y que encima se pueda crear tanto de forma manual como con programas… Eso sí, léete tu un fichero XAML escrito con Blend, que lo vas a flipar en colores.

Bueno, a lo que vamos, XAML tiene que poder interactuar de alguna forma con el código. Para evitarnos cosas como MFC, Microsoft permitió que se pudiera definir una misma clase en más de un fichero. Y nacieron las clase parciales. 

La idea es bien sencilla. XAML conoce una parte de la clase que define la ventana, y el programador conoce otra. Luego el compilador las une y hemos conseguido nuestro objetivo.

Pues bien, C++/CX implementa clases parciales de forma casi idéntica a C#. Es la única forma de que C++ pueda entenderse con XAML sin hacer virguerías todavía peores. 

En resumen:

No está definido en el estándar de C++11.

Sólo funciona para ref class. O en otras palabras: no vale para código C++ clásico ni para la parte clásica de una aplicación Metro escrita en C++/CX.

Se añade una nueva palabra reservada, partial, que debe ir en todas las declaraciones menos en una. 

Tomándolo del artículo en inglés en el que me baso, os pego un ejemplo:

 

// foo.private.h

#pragma once

 

partial ref class foo // <- here the partial keyword is used

{

private:

   int _id;

   Platform::String^ _name;

};

// foo.public.h

#pragma once

#include «foo.private.h»

 

ref class foo // <- partial keyword is not used here

{

public:

   int GetId();

   Platform::String^ GetName();

};

// foo.cpp

#include «pch.h»

#include «foo.public.h»

 

int foo::GetId() {return _id;}

Platform::String^ foo::GetName {return _name;}

 

Es decir, cuando declaremos una clase en varios ficheros, todos ellos deben llevar la palabra reservada partial excepto uno de ellos, que hará de concentrador. Supongo que esto facilita la tarea del compilador, que irá anotando las partes parciales y las irá añadiendo poco a poco a la otra de forma dinámica y conforme se vaya encontrando el código. Y finalmente, en uno o más CPP definimos los métodos y demás. Aquí ya no hace falta para nada la palabra partial porque eso ya lo podíamos hacer antes sin problema alguno.

Esto nos lleva al dibujo siguiente, tomado también del artículo citado:

 

xaml_cpp

 

Eso es lo que hace Visual C++ a la hora de crear una ventana, generando estos cinco ficheros. El XAML contiene la definición de la ventana y todo lo que pongamos dentro, y es idéntico a uno generado en C#. También genera otros dos con los nombres terminados en .g.h y en .g.cpp, que contienen código necesario para que el sistema pueda enlazar el archivo XAML con el código fuente que hayamos podido editar, que a su vez reside en otros dos sendos ficheros con las extensiones de .xaml.h y .xaml.cpp. 

Nuestro código debe ir en los ficheros terminados en xaml (para la definición de la parte visual), xaml.h (para la declaración de la clase que representa la ventana) y xaml.cpp para todo lo demás.

Debemos ser muy cuidadosos en no tocar los otros dos ficheros, que suelen ser generados de forma automática al vuelo por Visual Studio (y supongo que por Blend, pero eso no lo he probado todavía) y que, si hacemos algo mal, podemos tirar abajo el diseñador y luego la aplicación no se cargará bien. Digamos que dichos ficheros son los equivalentes al InitializeComponents() de WindowsForms y que, si los tocamos sin conocimiento de causa, podemos dejar inservible nuestra ventana.

Os dejo que juguéis con lo descubierto. Creaos una aplicación vacía, ponedle un botón o lo que querás y añadidle un evento.

 

 

 

 

C++/CX (III). Objetos COM

Decíamos ayer y antes de ayer que para crear aplicaciones Metro en Windows 8 podíamos usar, o bien el .NET Framework 4.5 con C# y VB.NET o bien hacerlo con el tradicional C++. Ya conocemos que Microsoft se ha dado cuenta de que la cosa manejada no deja de ser un poco juguete comparada con la nativa, y que hay muchísimas empresas que siguen, no solo con C++, sino incluso con MFC.

Independientemente de eso, lo cierto es que el API para Metro no es más que una variación de Win32, empaquetada y ofrecida mediante objetos COM nativos. La idea es cambiar Win32 y prohibirla para Metro, ofreciendo su equivalente mediante la biblioteca WRL que no es más que un encapsulado exportado mediante COM.

Aquí parece como si Microsoft matara dos pájaros de un tiro, ya que .NET utiliza COM internamente, o lo más parecido y cercano a ello. Por lo tanto, lo exportado mediante la WRL es tomado, por un lado por .NET y por el otro por C++ con su extensión CX.

Tenemos que decir que C++/CX es código nativo. Sin recolector de basura. Sin máquina virtual.  Compilado para un procesador específico. No es más que nuestro código escrito en C++ que utiliza objetos COM envueltos en una serie de clases al estilo de .NET. De hecho, la sintaxis de C++/CX es la misma que la de C++/CLI, por lo que en un principio puede llevar a confusión.

De todos modos, para aquellos que hayan leído el Rationale de Sutter (versión en español de Octavio Hernández y del que suscribe aquí), sabrán que es la única otra sintaxis posible y, o bien escribimos en C++/CLI para el .NET clásico (léase Windows Forms) o bien lo hacemos en C++/CX para Metro. Y si bien podemos hacer ambas cosas para Windows 8, las aplicaciones C++/CLI serán las tradicionales, y las C++/CX las Metro.

Con esto queremos decir que, usando C++/CX, tenemos acceso a toda la parafernalia nativa de C++ como la STL, Boost, C++11… y encima desarrollar para Metro. O dicho de otro modo: cualquier código que tengamos que no haga uso de ventanas ni de Win32 de forma directa no servirá para las aplicaciones Metro.

***

La parte CX se activa con la opción /ZW del compilador, y lo que hace es mapear los objetos COM en clases normales y corrientes. Allí donde antes teníamos que enfangarnos con IInspectable, y usar toda la parafernalia COM, ahora simplemente tenemos que usar una ref class normal y corriente con sus constructores, destructores, propiedades, delegados y métodos que recibirán los tipos de datos más estándar y que devolverán también valores estándar.

O en otras palabras: las clases que nos ofrece el API de Metro (por llamarlo de alguna manera, ya que es el API de WRL) son envoltorios a objetos COM WRL. Y de igual forma que los programadores de Windows han construido la WRL, nosotros también podremos tener objetos del mismo tipo, hechos por nosotros y ofrecidos a terceros. 

Supongamos que tenemos una clase cualquiera con un método llamado Compute que toma dos enteros y devuelve un valor de estado. Para nosotros, que usamos dicha clase, tan sólo tenemos que llamar al método y esperar el resultado.

Pero internamente, lo que está haciendo el sugar syntax de la parte CX del compilador, es algo así:

 

//Parte del “consumidor” de la case
inline int Computer::Compute(int first, int second) {
    int result;
    HRESULT hr = ___impl_Compute(this, first, second, &result);
    if (hr != 0) ___impl_throw_for_hr(hr);
    return result;

 

Y luego, el método __impl_Compute, que está en el lado del componente (si fuera una clase WRL estaría dentro de la WRL), sería algo así:

 

HRESULT __stdcall ___impl_Compute(Computer* cmp, 

  int first, int second, int* result) { 

    try { *result = cmp->Compute(first, second); } 

    catch(Platform::Exception^ e) { return e->HResult; } 

    return S_OK; 

}

 

De este modo vemos cómo podemos acceder a un método sin toda la parafernalia ni las ofuscaciones de COM. Y no queremos entrar en detalles sobre por qué COM es tan así, mayormente porque no tenemos ni repajolera idea.

No obstante, si así lo queremos por detalles de la implementación o simplemente por ser guays, tenemos acceso a la parte interna de WRL de la siguiente manera:

 

//Assuming 32-bit pointers 

Computer^ computer = ref new Computer; 

int* vtable_array = (int*)computer; 

int* icomputer_vtable = (int*)vtable_array[0]; 

int* compute_will_be_fptr = (int*)icomputer_vtable[6]; 

typedef HRESULT (__stdcall *compute_fptr_t)(Computer*, 

  int, int, int*); 

compute_fptr_t compute_fptr = (compute_fptr_t)compute_will_be_fptr; 

//…use compute_fptr freely 🙂

 

No voy a comentar nada de aquí porque simplemente me parece algo demasiado barroco y supongo que sólo será útil si te encuentras con algún bug en la parte CX del compilador… También podemos acceder a la interfaz COM pura a través del método RoActivateInstance, pero lo dejamos para los hardcore.

***

Finalmente hay una opción del compilador no documentada para que éste nos muestre una estructura detallada del componente WinRT que especifiquemos: 

 

/d1reportSingleClassLayout<CLASSNAME>

 

Y de nuevo dejamos la opción para los aventureros, que yo ya me he cansado de escribir por hoy.

 

Menuda porquería de gestión de memoria que tiene el OS X

A veces, cuando uno es un swicher de pro como yo, se encuentra con cosas que le resultan un tanto kafkianas como la que os voy a contar.

¿Tiene alguien queja de la gestión de memoria de Windows? No me refiero a si consume más o menos, sino a si funciona como debe, sin que haga cosas raras. ¿A que no? Pues en OS X (los MAC para los despistados), dicha gestión deja mucho que desear.

Hace tiempo empecé a leer en los blogs fanboys la existencia de ciertas aplicaciones que liberaban y optimizaban la memoria de los MAC. En principio algo similar a los supuestos optimizadores de memoria en Windows, pero para OS X. Y si en Windows no hacen falta y sólo consumen recursos, en OS X debería ser lo mismo o, en opinión de los expertos, todavía más inútiles que en la plataforma de Microsoft.

Yo fui uno de esos que comenzó a defender a capa y espada la gestión de memoria del OS X sin haber hecho ninguna prueba porque suponía que era una cosa que se caía por su propio peso: si un sistema operativo es incapaz de gestionar bien su memoria, poco útil va a ser…

Y de hecho, igual que pasó en su momento cuando se promocionaban ese tipo de aplicaciones para Windows, con artículos pagados y demás, se armaron en los citados blogs unas buenas trifulcas sobre el tema, con razonamientos a favor y en contra más o menos elaborados y veraces…

Una puntualización. En OS X, cuando tu cierras una aplicación, está no se cierra realmente, sino que se suspende y queda residente en memoria. Es lo que ocurre cuando le das al aspa de cerrar, o cuando presionas Command-W. Si realmente quieres retirarla de la memoria, o cerrarla ala Windows, tienes que presionar Command-Q o hacerlo a mano desde el Dock. Aquí hablamos de cerrarla realmente, que es cuando se debería liberar su memoria. No obstante, hay programas que realmente se cierran ellos solos, como el gestor de libros Calibre.

Por lo tanto, en OS X tenemos dos formas de cerrar una aplicación. En la primera realmente no se está cerrando, sino que se está ocultando y no es aplicable lo que estamos hablando aquí. Sería el equivalente de minimizar en Windows.

En OS X, la memoria se va asignando pero no liberando. Es decir, tu abres un programa, lo usas y luego lo cierras del todo. La memoria asignada no se libera, sino que queda asignada por si se vuelve a abrir la aplicación y se aprovecha la huella de memoria ya existente.

Por lo tanto, conforme vas abriendo y cerrando aplicaciones la memoria se va llenando poco a poco hasta que apenas queda libre. Hasta aquí la cosa está bien, porque de este modo mantenemos una caché que podría resultar en un aumento de rendimiento.

Y a veces es así. La segunda vez que abres ciertos programas, estos se cargan mucho más deprisa porque recuperan su imagen de la memoria física. Por ejemplo, en el caso del Opera con varios miles de mensajes de correos y de news, la diferencia es abismal. De tardar como treinta segundos o más a ser completamente instantánea.

Según la teoría, una vez que se ha ocupado toda la memoria y se necesita más, es esa caché la que se va liberando según un algoritmo que no me he preocupado en mirar. 

Eso es la teoría. La práctica es otra: se tira de swap y el rendimiento de tu MAC empieza a caer en picado y oyes cómo empiezan a rascar los discos duros. Y nadie puede negármelo porque lo he comprobado yo mismo esta mañana.

Todo ha comenzado pasándome del iMAC al Air la biblioteca del iTunes. Para ello he iniciado el AirDrop y con ambos iTunes cerrados, lo he copiado. En el Air estaba vigilando el uso de procesador del Sparrow, que me tiene mosca, así que he abierto el monitor de actividad en el iMAC. 

La primera en la frente: de los 12GB de RAM que tiene el iMAC, he visto cómo conforme si iban pasando los ficheros de uno a otro se iba quedando en cero libres. Una vez ha terminado de copiar, he abierto varios programas como el Word, el Pages y el ordenador ha comenzado a tirar de swap en lugar de liberar la memoria inactiva. Los he cerrado del todo y no ha decrecido el consumo. 

Para completar el ejercicio he lanzado una máquina virtual que consume 2GB de memoria y ni aun así se ha liberado lo ocupado, sino que los discos han empezado a rascar todavía más furiosamente y el rendimiento ha caído en picado…

Tras eso me he ido a la App Store y me he bajado un liberador de RAM. Al poco de ejecutarlo y lanzar la limpieza de la misma, mano de santo, oye. Los discos han dejado de rascar y me ha dejado algo más de 8GB de RAM libres, que han subido a 10 cuando lo he vuelto a ejecutar tras cerrar la máquina virtual.

El problema, evidentemente, no está en el consumo de RAM. Por mi como si se ocupa toda, sino en el hecho de que un consumo real de 2GB del sistema operativo más otros 2 GB de la máquina virtual, han tirado abajo el rendimiento de un iMAC con 12GB de RAM y un i7 con 8 cores…

Pensaba que Apple podía hacerlo mejor, pero al final resulta que son unos chapuceros de mucho cuidado…

Por si os interesa, he probado el FreeMemory y tras comprobar que funcionaba bien, he comprado la versión Pro por tres cuartos de euro.

ExFAT 1, XBOX 0, Microsoft -infinito

Esta tarde nos hemos puesto a ver una película en la XBOX… lo que ha supuesto toda una odisea. Me explico.

Enciendo la consola y hala, actualización. No suelo encenderla muy a menudo, pero joder, que pase como con los PC… Pero el tema no es que haya sido una, sino que han sido dos, la segunda de ellas muy muy gorda. Tanto, que supongo que se ha actualizado toda entera.

La primera en la frente: no he podido usar la consola cuando he querido, sino que me he tenido que esperar más de media hora. Vale, podría haber decidido actualizarla luego, pero cualquiera se fía de un equipo que se conecta a internet con la que está cayendo…

Vale. Entro ya en el interfaz y meto un USB normal y corriente de 16GB… No lo detecta. Lo saco y meto un segundo de 4 GB, previa copia de lo que íbamos a ver. Tampoco lo coge. De 1 GB. Ni con esas.

Vale, estaban en ExFAT y la consola ¡¡no soporta los propios formatos de Microsoft!! Está bien que no lo haga cuando salió el sistema de ficheros, pero éste lleva ya varios años en el mercado.

Entiendo que no lea NTFS, ni HPFS, ni Ext2, ni ReiserFS… Es razonable a más no poder, ¡pero que un producto de Microsoft sea incapaz de leer sus propios formatos!…

Porque entendamos que si bien NTFS es un sistema “enterprise”, ExFAT es comercial y pretende ser la sustitución del veterano FAT… ¡Joder, si hasta los MAC los leen!

Y lo peor no es eso, lo peor es que una vez que ha sido tocado por la XBOX, ese USB deja de poder aceptar nuevo contenido. Es decir, que sólo deja ver y borrar ficheros, pero no añadir.

***

Al final, mientras reformateaba el disco a FAT32, y copiaba los archivos, me dio por navegar un rato con la consola…

Ahora se pueden instalar aplicaciones. Vale. Me instalo el visor de Youtube, por hacer algo. Se instala sin problemas.

Lo lanzo segundos después ¡y me dice que tiene que actualizarse! Hay que joderse, amigo Sancho… ¡¡Pero si está recién bajado de la tienda!!

En fin, se actualiza, entro y… necesito una cuenta Gold. La mía es la normal, sin pago…

¿Por qué cojones no me dice que es necesaria una cuenta Gold antes de instalar? Pues si piensan que tras la instalación voy a pasar por caja van arreglados.

Por seguir probando (ya que todavía no se habían copiado los ficheros en el disco USB), instalo la aplicación de DailyMotion. Esta al menos me avisa de que habrá cosas del interfaz no soportadas en la consola, pero cuando lo lanzo e intento ver un vídeo… me vuelve a pedir la cuenta Gold.

***

Vamos, lo dicho, un gigantesco despropósito de cosas que me resultan completamente incomprensibles… No sé quiénes tomarán las decisiones, pero seguro que serían más útiles cavando bancales de ajos que decidiendo qué va y qué no va en los productos de Microsoft. 

Y no hablo de los problemas de conexión que tengo con el Media Center (de Microsoft) y el NAS (este no es de MS), aunque el último suele ir sensiblemente mejor que el primero.

***

Básicamente, que les den.

Culico que veo cubico que deseo

Creo que ya tengo un post con el mismo título por algún lado, pero no puedo resistirme a comentar algunas cosas sobre los últimos movimientos de Microsoft.

Hay cosas de las que de momento no puedo hablar, pero hay otras que sí, y la verdad es que resultan un poco risibles porque, al menos desde mi punto de vista, son la respuesta incorrecta a una competencia mal entendida.

Os comento.

Apple, de vez en cuando, dice cosas como que el Flash es malo y sus productos no lo llevan, o que la disquetera está obsoleta, o que simplemente se acabaron las instalaciones con unidad de disco…

Y eso primero genera polémica, y luego resulta que tenían razón…

Pues bien, Microsoft quiere hacer lo mismo, pero como ya sabemos dónde tienen el estilo, la cosa termina, seguro, en unas risas y en una l,vuelta atrás.

Por un lado, mientras todos los fabricantes de móviles hacen cada vez equipos más potentes y con más funcionalidades dentro de su sistema operativo, mientras que mantienen otras restricciones más o menos incomprensibles para los expertos, Microsoft ha decidido hacer lo mismo… pero a su manera.

En general, un producto de Microsoft siempre ha ido creciendo tanto en vertical (más necesidad de hardware) como en horizontal (un API más rico y más completo). Esto ha llevado siempre a que la siguiente versión ha necesitado más memoria y más procesador para funcionar bien. En la parte de las APIs, han preferido enmarranar y convertir algo existente en más complejo en lugar de hacer borrón y cuenta nueva o simplemente añadir un API nuevo con más funcionalidad y dejar que el anterior muera…

Tampoco vamos a hablar del hecho de que, cuando han conseguido una tecnología madura y estable, en lugar de mantenerla y ampliarla, han decidido reinventar la rueda y vuelta a empezar: nuevo de todo, nuevos bugs, etc…

Pues bien, como decía, en un intento de paralelizarse a Apple, en lugar de cambiar para bien, lo hacen para mal. Hablo ahora de Windows Phone de 256 megas de RAM, que enmierdan todavía más ya la mierdosa API de ese sistema operativo. Quitan cosas útiles y añaden nuevas inútiles (y ya hablaré de eso en otro momento). Básicamente quieren copiar, pero copian mal.

***

Apple retiró su Media Center por los motivos que fueran. Microsoft lo retira en su Windows 8. Nada, hay que hacer lo mismo.

***

Y ahora llega el colmo de los colmos. Windows 8 no podrá reproducir DVD sin programas externos porque dicen que el uso del DVD está rápido decline en los ordenadores…

En fin, lo dicho, copia, pero copia bien, joder, y no vayas haciendo este tipo de tonterías…