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.

 

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.

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.

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…

Leo en Twitter un par de preguntas más que curiosas sobre dos cosas que se dan por supuestas en el desarrollo orientado a objetos. Aunque una de ellas está formulada al revés, yo aquí le voy a dar el sentido correcto, e intentaré responder, en la medida de mis conocimientos, a ambas.

***

La primera de ellas es “¿por qué las variables de una clase no deben ser públicas?”

Es una de las primeras cosas que nos enseñan en la POO. Extendiendo la pregunta al ámbito completo, el concepto se conoce como “ocultación de datos”, y se extiende no sólo a las variables de clase, sino también a los objetos en sí y en general al programa completo.

Por poner un caso extremo, en la mayoría de Frameworks serios, el punto de entrada de un programa cualquiera debería ser:

 

MiApp theApp;

theApp.Run();

 

Vale, es un poco extremo, pero a ese nivel es lo que necesitamos: una aplicación, y que la vamos a ejecutar. No nos hace falta nada más ni tenemos que conocer nada más a ese nivel.

Es decir, uno de los motivos de la ocultación de datos es dar a conocer únicamente lo estrictamente necesario, y de hecho no nos importa si theApp tiene una variable llamada Juanito o Pepito porque no tiene utilidad conocerlo a ese nivel.

Y de hecho no nos interesa que nadie sepa la estructura interna de MiApp porque sencillamente ahí no podemos y no debemos hacer nada más que ejecutar el objeto que es la representación en memoria de nuestra aplicación. Quizás, o bien en el constructor o bien en el método Run(), pasar los argumentos con los que ha sido llamada la aplicación, pero sólo si es pertinente y nos interesa.

La regla nos dice que si no lo necesitamos a ese nivel, no lo hagamos público. Pero claro, todavía no he explicado por qué. Simplemente he definido la regla: oculta todo lo que puedas.

Jorge Serrano, respondiendo en Twitter, lo ha dicho bastante claro: No te interesa que nadie te pueda cambiar los zapatos sin tu consentimiento. Yo diría que cada perro debe lamerse su pijo, expresión más castiza. Imagina que vas andando por el monte, y alguien te cambia tus botas de trekking por unas chanclas de playa sin tu consentimiento… O que estás en una reunión de alto copete y una chavala empieza a esto…, lamerte el tema…

Reformulado en código, y retrocediendo un poco, la idea es bastante interesante.

En la programación procedural clásica (es decir, C y similares), y tal y como lo dijo Stroustrup en no recuerdo qué lugar, un programa es un conjunto de funciones que menean un conjunto de datos.

En teoría, cualquier función podría tocar cualquier dato. Digo en teoría porque en C y similares también hay métodos, más primitivos, para ocultar datos. Quien haya desarrollado aplicaciones más o menos grandes con esta filosofía, se habrá encontrado con serios problemas:

  • Métodos que cambian datos que no deberían cambiar.
  • Datos que deberían ser diferentes pero que por un despiste tienen el mismo nombre y que son combinados por el enlazador como uno solo.

Poniéndolo en otras palabras: se pueden dar situaciones en las que la modificación de un dato genere efectos laterales que terminen en un comportamiento no deseado, o incluso generar una onda de interferencia que termine tumbando la aplicación.

Lo mismo podría pasar con dos variables que accidentalmente han sido nombradas igual. Un compilador moderno debería avisar de este último caso a nivel de enlazador, y en general, al menos con Visual C++, así ocurre. Otra cosa es que el programador novel le haga caso o se dé cuenta del aviso. Y no todos los compiladores notifican de este hecho, sobre todo los de plataforma cruzada para sistemas embebidos, que suelen ser bastante antiguos.

Volviendo al tema central, la OO intenta solucionar este problema con las clases y la ocultación de datos. Es decir, una clase es una serie de métodos que definen cómo tocar a una serie de datos de forma auto contenida. Y hasta la fecha es la mejor solución que se ha podido encontrar, y si alguien conoce alguna mejor (que no sea una paja mental), le vaticino los laureles del éxito más absoluto y arrollador.

En otras palabras: una clase es una entidad con un comportamiento definido por su código y es algo opaco a cualquier cosa que intente ver su interior excepto un interfaz público que sirva para tratar con ella.

Y hay varias razones, todas ellas muy poderosas, para que esto deba ser así, lo que lleva implícito una serie de obligaciones: ocultación de datos, interfaz pública y autocontención. Otras características como polimorfismo extienden pero no obligan, por lo que las vamos a obviar.

Volviendo al ejemplo de los zapatos, pensemos en un objeto zapato genérico. Cuando construyamos una persona, a la clase persona le añadimos dos objetos zapatos (que podrían ir en un array, pero no es imprescindible).

Y ahora viene el truco del almendruco. Atarse los cordones. Podemos hacerlo de varias formas.

La más chapucera es acceder al método miembro cordón de cada zapato y atarlo, ejecutando una serie de acciones (código) sobre dichos cordones. Para ello necesitamos que cordón sea público.

¿Pero qué pasa si tenemos varios tipos de zapatos? Por ejemplo, unos que lleven hebillas. Ups. El código para atar zapatos que está en la clase persona ya no nos sirve…

Si embargo, si definimos un zapato padre que tenga un método llamado AtarCordones() y que internamente use el dato miembro cordón para realizar la misma operación que antes hacíamos desde la clase persona, cuando heredemos de dicho zapato una nueva clase llamada sandalia, tan sólo tendremos que redefinir el método AtarCordones() que, en lugar de usar cordón, usará hebilla y una serie de acciones con ellas.

Y lo que es más importante, la clase contenedora, persona, se desentiende de qué zapato tenemos, de si tiene hebillas o cordones. Simplemente llama a zapato.AtarCordones() y la acción estará hecha.

[Hablando más seriamente, deberíamos tener una clase base virtual llamada, por ejemplo, ZapatoGenérico que defina un método virtual llamado AtatCordones(). Y luego deberíamos heredar de ahí el Zapato normal y la Sandalia. Y quizás otras variantes de calzado.]

Por lo tanto, al ocultar los datos internos y dejar una interfaz pública, ganamos muchas cosas:

  • Los objetos que manipulen nuestro objeto lo harán a través de una interfaz definida y que debe ser siempre la misma (con la salvedad de los pasos de refactorización que sean necesarios y que cambien los nombres o la propia interfaz).
  • El punto de arriba mejora la claridad del código,
  • Nos evita tener que depurar los objetos llamadores porque no ha cambiado nada en ellos,
  • Nos permite cambiar el comportamiento interno del objeto manipulado sin tener que preocuparnos de la clase manejadora,
  • Permite el efecto biblioteca (comentado por Herb Sutter en su Rationale a C++/CLI, que su vez lo toma de Stroustrup): podemos meter la clase Zapato en una biblioteca, y podremos cambiar su comportamiento interno sin tener que recompilar el código que la use,
  • Oculta la visibilidad, permitiendo un código mucho más limpio y con menos interferencias y símbolos globales, que al menos en C++ pueden lentificar la compilación en grado sumo.
  • Acelera la carga en tiempo de ejecución, porque el cargador del sistema, al tener menos símbolos públicos, tiene que inicializar y relacionar menos cosas.

Vale, creo que no se me escapa nada, y si lo hiciera, con los puntos de arriba hay suficiente.

Todo esto nos lleva a una serie de reglas de diseño con las clases que, al menos yo, llevo a rajatabla:

  • Oculta todo lo que puedas.
  • Usa el nivel más cerrado posible: private en C++ para todo lo que puedas. Luego, cuando refactorices y necesites que algo sea conocido por clases hijas, pásalo a protected, pero con sumo cuidado ya que si hay (o se quiere) efecto lateral, mejor pon un método protegido en el padre que pueda ser llamado por el hijo para acceder a ese miembro privado.
  • Define interfaces públicos, pero los menos posibles. Si un zapato no va desatar los cordones, no lo definas. Si lo necesitas, ya lo definirás. (Aquí hay que mantener cierto equilibrio, porque si sabes que lo puedes necesitar, mejor lo declaras pero no lo defines –cuerpo vacío-, ya que podría ser peor luego tener que cambiar la interfaz ya definida y usada).
  • Documenta por qué, no cómo (el cómo ya te lo dice el propio código, a no ser que sea algún algoritmo complejo, y en ese caso en el 99% de las veces seguro que se puede hacer de otra forma más sencilla).

Finalmente esto nos lleva a un problema que plantea mucha gente, y es que toda esa ocultación y esos métodos de acceso pueden volver un programa extremadamente lento.

Os lo puedo asegurar: eso fue en tiempos pasados, cuando los compiladores eran animales mitológicos y se sabía poco sobre ellos.  Ahora, cualquier compilador medio decente se va a comer tus miles de líneas de código en un santiamén y va a generar mejor código que el que tu pudieras hacer a mano saltándote todos esos pasos. Al menos en C++ y quiero creer que también en C#.

***

Bueno, ahora viene la segunda pregunta, que reformulo pues está planteada con los conceptos cambiados: “¿Alguno sabe la razón de por qué las variables se pasan por valor y los objetos por referencia?” Hablamos de C#, ya que en C++ y C++/CLI podemos pasarlos como nos salga de la pepitilla…

Para responder a esta pregunta debemos meternos un poco en cómo funcionan los compiladores.

Una variable nativa, digamos un entero, ocupa 4 bytes (por decir algo, todo depende de dónde ejecutemos). Un objeto ocupa tanto como la suma de sus datos miembro y una o varias vtable en caso de que tenga métodos virtuales y del nivel de anidación de la herencia (así como de lo bueno que sea el compilador).

[Una vtable es un array de punteros a función que, en tiempo de ejecución, determinan qué método se va a ejecutar dentro de un objeto con métodos virtuales. Un buen compilador resumirá esto en cambiar un call directo a un call indirecto en base a un índice almacenado en algún lugar.]

Cuando nosotros definimos una clase, y a partir de ella instanciamos un objeto, el compilador (y en tiempo de compilación) hace un pase de manos y agrupa todos los métodos miembro en un bloque que junta con los demás métodos miembro de las demás clases, añadiendo unas firmas especiales a los nombres de función.

Digamos que una vez compilado, un programa OO se convierte en un programa no OO que tiene una serie de funciones globales que acceden y modifican una serie de datos… ¿Os suena, verdad? Es que es la única forma de hacerlo, os lo puedo asegurar. La ventaja está en que, salvo oscurísimos errores del compilador que cada vez ocurren con menos frecuencia, a todos los efectos, el comportamiento final simula ser completamente orientado a objetos.

Bueno, cuando pasamos parámetros en una llamada a método, el sistema usa una pila, que es un área de la memoria especialmente destinada a las tareas descritas.

No vamos a entrar en detalles técnicos, pero la cosa funciona así: el compilador pone en la pila los datos a pasar, copiándolos quizá de otro punto de la pila. Entonces hace un call en ensamblador a la función que hemos llamado, y cuando entremos en ella, sabrá que en la cima de la pila tiene sus parámetros.

Cuando pasamos un parámetro por valor, estamos copiando dicho valor en la pila. Si es un entero, ocupará 4 bytes. Si es un objeto, ocupará tantos bytes como datos miembro tenga (ojo, sólo los datos, no el código), más las tablas virtuales más algún que otro elemento más que hace la función de metadatos del objeto pasado.

Si el objeto ocupa 10 bytes, se copiarán, y si ocupa 100, 1K o 100K, se tendrán que copiar absolutamente todos los bytes. Dependiendo de qué objeto, la copia podría ser onerosa en tiempo de ejecución y gasto de memoria.

Cuando pasamos un objeto por referencia, estamos pasando un puntero al dato. No importa en qué lenguaje estemos, siempre es un puntero. Todo lo demás lo hace el sugar syntax del lenguaje, que nos endulza la sintaxis y el operar con ellos.

En este caso, de media, una referencia a un objeto en C#, y si no lo han cambiado, ocupa unos 10 bytes independientemente de qué tamaño real tenga el objeto en sí.

Por lo tanto, ahora vemos por qué en C# un objeto se pasa por referencia y un tipo nativo por valor: optimización.

Esto genera una serie de idiosincrasias en C# que al menos a mi no me gustan mucho, ya que estamos obligando al programador a que lo haga al estilo del lenguaje y no como uno quiera (ya sabéis, eso de “programar en” y “programar con”).

La optimización es la adecuada para la mayoría de casos, pero a veces querríamos hacerlo de otra forma, y es cuando uno ve las limitaciones del lenguaje. En el caso que nos ocupa, un objeto no se puede pasar por valor, lo que fuerza a copiarlo a mano si vamos a modificarlo y no queremos que el original sufra cambios. Y a veces eso es difícil, ya que en algunos casos la copia es de nuevo por valor y no se produce la mutación a nuevo objeto cuando modificamos la referencia creada, y no podemos hacer nada porque el C# (y el .NET) son así.

Sin embargo sí que podemos pasar un tipo nativo por referencia, añadiendo ref al parámetro (con lo cual modificaremos su valor desde dentro de la función llamada). No obstante, la implementación es una chapuza como un castillo, ya que la cosa funciona así dadas las severas limitaciones de la máquina virtual .NET: El valor a pasar por referencia se copia al montículo (heap en inglés, que es donde se guardan los objetos y demás elementos instanciados por referencia) y entonces se pasa, en la pila, una referencia a ese valor puesto en el montículo. Cuando salimos de la función llamada, el sistema coge del montículo el valor modificado y lo vuelve a poner en la pila.

Es lo que se llama box/unbox, y viene determinado por la limitación del .NET de acceder a la pila cuando el elemento a tocar no está encima de ella. La única ventaja que obtenemos de esto es que es mucho más difícil generar una inyección de código mediante el envenenamiento de los parámetros de retorno de la pila.

***

Para aquellos que quieran tener una visión más amplia de la orientación a objetos, así como muchas explicaciones, les recomiendo el libro de Bertrand Meyer, Construcción de software orientado a objetos Segunda Edición, que es un tocho de más de mil páginas denso como él solo… Pese al proselitismo hacia Eiffel, es un gran libro. Hay edición en castellano de Prentice Hall (que es la que yo tengo), pero no sé si se podrá encontrar o no.

Otro no menor pero más práctico, es Code Complete 2 de Steven C. McConnell. Este es mucho más práctico y orientado hacia el código real que escribimos las personas normales.

Hay que joderse, que dijo aquél. Este podría ser el resumen de esta entrada. Ahora mismo veréis por qué.

***

Estoy empezando a jugar de forma más o menos seria con Windows Phone. Ya cuando salió, el no poder ejecutar código nativo básicamente me hizo pensar que Microsoft había perdido el tiempo y que WP iba a ser un gran y nuevo fracaso de la compañía que había perdido el norte, el sur, el este y el oeste…

Pasa el tiempo y pese a todos los intentos de MS, WP no levanta cabeza. Ni cuota de mercado ni aplicaciones, comparándolo con Android e iOS, que crecieron mucho más rápido.

Ahora sé algunas razones, imposibilidad de usar C++ incluída.

***

Windows Phone 7.0 no tiene sockets. Toma ya. Increíble. Para los legos: no hay posibilidad de crear ningún tipo de aplicación de chat, ni de comunicación remota a servidores ni nada parecido. Todo hay que hacerlo mediante HTTP, que no conserva el estado y necesita sobredimensionar el lado servidor frente al cliente…

Whidows Phone 7.5 tiene sockets… de aquella manera. Cuando la aplicación pasa a background el socket se cierra, con lo que pierdes la persistencia en la comunicación. Aquí lo puedes solucionar mediante técnicas Push (que todavía no he visto e ignoro las limitaciones y ventajas que puedan tener). Pero de momento, aplicaciones verticales que requieran una conexión permanente tampoco están permitidas.

***

Ahora llega la última versión, con dispostivos de 256 MB de memoria… Y la vuelven a cagar. Dadas las limitaciones de los mismos, dejan de funcionar las tareas periódicas y las intensivas… Y te dicen que cuando lances la aplicación mires en qué dispositivos estás ejecutando y uses secuencias if/else para cambiar el comportamiento.

En primer lugar eso es una soberana imbecilidad como una casa. ¿Tienes que codificar las cosas dos veces? Pues no, tendrás que hacerlo todo con la limitación predicha, porque si lo puedes hacer sin esos elementos, es una soberana gilipollez repetir el código. El problema vendrá cuando sin eso no puedas hacerlo.

En segundo lugar, mientras los demás fabricantes implementan mejoras y optimizan el código de sus sistemas operativos, Microsoft hace lo contrario. Apple pasa de dispositvos de 256 MB de RAM a 512 y luego a 1024. Microsof pasa de 512 a 256, llevándose cosas de en medio.

***

Recuerdo la presentación de Windows Phone: que si sólo .NET, que si sólo procesadores multicore, que si sólo dispositivos de gama alta… Al final tienen que pasar por el aro, pero en lugar de abrir el Windows CE interno al lenguaje C y/o C++ y quitar la mierda del .NET, que seguro consume 40 de los 60 MB de la huella de memoria de cada proceso, van y quitan prestaciones… porque lo de las tareas asíncronas es sólo una de tantas limitaciones impuestas, que podéis leer en la entrada que os enlazo más arriba.

***

Resumendo, que van de mal en peor. RFOG dixit.

No sé si reír o llorar, si partirme el culo de la risa o qué hacer. Os cuento rápidamente:

Embarcadero, actual dueño de RAD Studio, que combina Delphi, C++ Builder y otras herramientas, tiene por costumbre sacar, año sí y año también, una nueva versión de cada una de sus herramientas de desarrollo. Da igual en el estado en que estén: ellos, más o menos a finales de agosto, sacan lo que ellos llaman una nueva versión.

Digamos que es una suscripción anual encubierta, ya que la nueva soluciona algunos bugs de la anterior, y de paso añade unos cuantos más. El compilador de C++ está estirado hasta límites increíbles, y parece ser que están haciendo algo nuevo con soporte multiplataforma y mixto entre 32 y 64 bits. Ya veremos qué sacan.

Os decía que cada año hay una nueva versión del producto. En general suele ser bastante inestable y algunas veces completamente inusable en según qué escenarios. Hasta que no sacan el primer parche la cosa no empieza a ir medianamente bien. Debe ser que eso de probar antes de vender no va con ellos.

También suelen hacer algún tipo de oferta que viene a durar dos o tres meses. La más típica es la de que pagas un producto y te llevas otro igual. No obstante últimamente se ha puesto de moda primero limitar las actualizaciones de versiones demasiado viejas.

Es decir, que si tienes un C++Builder 5 no puedes, legalmente, actualizarte a C++Builder XE2 (la última) a precio de actualización, sino que tienes que pagar la versión completa. Comprarla la puedes comprar, pero cuando metes el número que te dan y tiras a activar te dice que nones, así que ándate con ojo.

Ya que estamos, y antes de entrar en el meollo de la entrada os cuento la última que han hecho. Dado el XE2 es la primera versión en la que se soportan los 64 bits para Delphi en Windows y la plataforma OS X (MAC) en 32 bits (que ya les vale), están sacando actualizaciones a bastante buen ritmo. De hecho la última que salió hace unos días fue la cuarta.

Es una actualización completa. Tienes que desinstalar el producto completo y volver a instalar la versión completa.

Pero eso no es lo único malo. Lo peor de todo es que esta nueva “actualización” rompe la compatibilidad binaria hacia atrás y, para más inri, hay algo que han hecho mal y el enlazador tiene serias limitaciones para generar programas en Firemonkey hasta el punto de que es completamente inusable si no aplicas una chapuza de las gordas…

Hay que joderse.

***

Bueno, ahora ya sí, lo que os quería contar. Os decía que primero te capan la posibilidad de actualización desde versiones antiguas. Eso deben haberlo hecho para forzar a los usuarios que todavía utilicen versiones viejas (recordemos que, al menos en el C++ Builder y para Windows, desde la versión 4 no han aportado nada realmente nuevo) a comprar una actualización o a perder definitivamente la posibilidad de hacerlo.

En cierta medida tiene su justificación, aunque si tu estás más que cómodo con tu C++Builder 4 ó 5, no tienes por qué actualizar para encontrarte con nuevos problemas y nuevas idiosincrasias impuestas por Embarcadero. Y de todos modos pienso que no es más que una técnica para intentar vender más.

No obstante el cachondeo viene ahora. La oferta comenzó en agosto de 2011, terminó en septiembre u octubre (no recuerdo exactamente cuándo), pero la ampliaron hasta diciembre. Una semana antes de caducar volvieron a ampliarla hasta no recuerdo qué fecha, y finalmente lo han vuelto a hacer hasta el 31 de marzo.

¿Sabéis lo que pienso? Que casi nadie les compra ya el producto, y con la tónica que llevan no creo que continúen teniendo mucho éxito. O se espabilan de una vez o los veo en el agujero, pese al bombazo de la multiplataforma (que por cierto ha pasado sin pena ni gloria en los medios de comunicación), que como ya os dije, vino traída de forma bastante chapucera.

Conforme va pasando el tiempo vemos cómo un producto que pudo haber sido de Microsoft y haber constituido la plataforma base nativa para Windows, va creciendo y estabilizándose poco a poco.

Hablo del framework de QT, creado por Trolltech, vendido a Nokia y, cuando ésta pasó a formar parte de Microsoft, cedido a Digia para el soporte. Resulta un producto un tanto movido, base de KDE y de muchos otros productos interesantes.

Hasta no hace mucho, utilizar QT Creator para construir este tipo de aplicaciones era un tanto cansino, porque el producto no estaba a la altura de un IDE medio decente. Tampoco es que ahora lo esté, porque sólo permite visualizar una ventana, y la depuración es, cuando va, lenta. Ni se te ocurra poner puntos de interrupción en diferentes hitos, porque algunas veces pararán y otras no. El inspector de variables locales tampoco anda muy fino que digamos.

No obstante QT sí que está muy maduro y funciona muy bien. Al menos en las partes que he usado, que son todo el tema de los Widgets y la sincronización. Eso sí, desde Visual Studio con su correspondiente plugin. Desde el propio Creator da verdadero asquito de usar.

Bueno, os decía que ahora el SDK de QT tiene hasta un instalador, tanto para MAC como para Windows y Linux. El de Windows va muy bien, lo uso en el trabajo y no he tenido problemas. (Y es por eso por lo que he dejado de hablar de Metro y C++ ya que estoy metido de lleno con QT y apenas tengo tiempo de mirar otras cosas. Ya sabéis, donde manda patrón no manda marinero).

No obstante, en el iMAC no conseguía instalarlo, e internet no es que me fuera de mucha ayuda… Hasta que de refilón, y mirando otra cosa, lo encontré.

***

Para instalar el SDK de QT es necesario tener xCode instalado previamente. Pero si la versión que tienes es la 4.3 el instalador de QT va a protestar y te va a decir que no tienes un compilador de C++ en tu equipo, pese a que xCode está ahí y compila sin problemas un proyecto…

¿La solución? Abrir xCode, ir a Preferencias, pestaña de Descargas, e instalar las Command Line Tools. Necesitas una cuenta de Developer en Apple, que es gratuita.

Una vez instalado eso, ya podrás poner en marcha tu copia de QT.

con no comments
Archivado en: ,,

Aquí.

Llevo bastante tiempo sin leer novedades literarias, y menos aún las de esta clase: Vivo o muerto, Tom Clancy y Grant Blackwood. Y suena a lo que es: un bestseller que aprovecha el tirón del 11S y que forma parte de la serie Jack Ryan del autor. Para los que no saben de qué va, estos libros son novelas de entretenimiento en los que el personaje Jack Ryan, primero analista de la CIA y luego más cosas, termina en medio de los berenjenales más típicos de este tipo de obras: terrorismo, espionaje, etc.. Las novelas estarían mejor si no tuvieran ese pro-USA tan acérrimo. Pero bueno, es lo que hay.

Si os preguntáis qué hace una entrada como esta en un blog como este, os lo diré: id a la página 168 de la edición de Umbriel de 2011 (la única por ahora) y leed conmigo:

 

“Y aunque hubieran examinado aquél [un CD grabado], no habrían visto más que un galimatías incomprensible: datos sólidamente cifrados en lenguaje de programación C++, carentes por completo de sentido.”

 

Sí, yo también me he asustado, y no poco. Vale, es una pifia del traductor, ¿no? Pues no, en el original pone:

 

“Even if that one had been examined, it would have been shown to contain gibberish, robustly encrypted data written in C++ computer code that made no sense at all,”

 

Bueno, pues ya lo sabéis, chicos, el C++ también sirve para encriptar datos. Ya sé que el obfuscated code puede ser difícil de entender, pero tanto como para incluir elementos encriptados en su código…

Desde luego hay quien oye campanas y se imagina belenes.

En fin.

Ya las hará el cliente y protestará. En el caso de que tengamos ganas, le ayudaremos. Si no, que se joda.

Esa parece ser la filosofía de Embarcadero para su producto RAD Studio XE2. Para hacernos una idea, lo que ahora trae el XE2 es lo que debería haber traído el XE original, pero ya sabemos, después de varios (muchos) años intentando convertir a la VCL en multiplataforma, llegan, compran un producto cualquiera, y en menos de seis meses lo integran en su RAD Studio, sustituyendo a la vetusta VCL que, por cierto, dio nacimiento a .NET cuando Microsoft se llevó a Anders de Borland.

El sistema de desarrollo es un tanto churrimangui, aunque parece ser que funciona. La idea es tener una máquina Windows con RAD Studio instalado. Puede ser una máquina virtual corriendo dentro de OS X, pero tened mucho cuidado con la compartición de perfiles y demás: en un tris tenéis que volver a activar, porque una de las cosas que mira el entorno para detectar que no lo han tocado es el nombre del equipo en la red. En fin.

Luego instalas un servidor en OS X, lo que, junto a un debugger de plataforma cruzada, puedes editar y compilar en la máquina Windows y ejecutar y depurar en el MAC. Digo churrimangui porque no es a lo que nos tiene habituados Borland, digo Embarcadero. Encima todo el tema al lado del MAC es por línea de comandos. Cualquier programador de hardware, o ya puestos de teléfonos y similares, verá el paralelismo evidente.

***

Pero bueno, no es de eso de lo que quiero hablar aquí. Hasta el 32 de diciembre del 2011, hay una oferta que si compras alguna versión del producto, te regalan otros. A veces ha sido comprar C++ Builder (o Delphi) y obtener el otro gratis. La de este año consiste en que te regalan más componentes y otros programas de la casa.

Uno de los productos es FastCube, componentes que te ayudan al análisis de datos. En mi caso no creo que me hagan falta, pero podría ser interesante para aquellos que hagan programas de gestión y tengan que presentar datos analizados.

Pues bien, las pruebas de integración de este producto con RAD Studio no se han hecho. No porque si instalas el componente, el producto deja de funcionar. No se trata de algunas configuraciones en concreto, ni que ocurra en ciertas máquinas: pasa siempre.

Si uno se pone a buscar en internet el error que da C++ Builder (que es el que falla, Delphi funciona bien), no encuentras absolutamente nada sobre el tema. Aplicando un poco de lógica, podemos llegar a varias posibles conclusiones:

  • Nadie está usando C++ Builder, o si lo está, no ha instalado dichos componentes.
  • Desde que han sacado la oferta, no han vendido ni una sola copia de C++ Builder o de RAD Studio.
  • Nadie está usando el producto.

Os dejo con la reflexión antes de pasar a la solución.

***

El problema se genera cuando la instalación del producto (que no es de Embarcadero, pero deberían haber hecho el test de integración antes de ponerlo a disposición de la gente tan alegremente) estropea por completo las rutas por defecto del compilador. Es decir, si abrimos el IDE (ya sea la versión completa de RAD Studio o personalidad de C++Builder), y nos vamos a Tools -> Options -> C++ Options -> Paths and Directories, las rutas de Include Path y de Library Path quedan completamente inutilizadas porque FastCube, en su soberana sabiduría, ha decidido que nadie más que él debe estar ahí.

Desinstalar el producto no soluciona nada, porque dichas rutas se quedan sin restaurar.

Por lo tanto, la solución pasa por volver a colocar allí dichas rutas. En mi caso son:

  • Include: $(CG_BOOST_ROOT)\boost\tr1\tr1;$(CG_BOOST_ROOT);$(BDSINCLUDE);$(BDSINCLUDE)\dinkumware;$(BDSINCLUDE)\windows\crtl;$(BDSINCLUDE)\windows\sdk;$(BDSINCLUDE)\windows\rtl;$(BDSINCLUDE)\windows\vcl;C:\Program Files (x86)\FastReports\LibD16;$(BDS)\RaveReports\Lib;C:\Program Files (x86)\Raize\CS5\Lib\RS-XE2\Win32
  • Lib: $(BDSLIB)\win32\release;$(BDSLIB)\win32\release\psdk;C:\Program Files (x86)\FastReports\LibD16;$(BDS)\RaveReports\Lib;C:\Program Files (x86)\Raize\CS5\Lib\RS-XE2\Win32

No te garantizo que la instalación haya tocado otras cosas, pero en mi caso, con volver a colocar ahí dichas cadenas, se soluciona el tema.

***

Por lo tanto, otro coscorrón más para Embarcadero. Y ya os diré cómo funciona el producto, porque voy a usarlo para un proyecto personal.

 

Os lo juro. Estoy hasta los putísimos cojones de Windows, de MAC y de la madre que los parió a todos. El primero por pensarse que todo le pertenece, incluyendo las particiones  HFS+, y el segundo por pensar que todos los usuarios son tontos del culo.

No tengo muchas ganas de escribir, así que voy a ser bastante escueto.

Escenario: Windows/MAC con Boot Camp y arranque dual. Como Windows asigna las unidades como le sale de los cojones, entro en el Administrador de Discos y las cambio a los valores que quiero.

Vale, todo bien en Windows. Inicio OS X y… una de las tres particiones no se carga. Es decir, habiendo cambiado la letra de unidad a dos particiones HFS+ desde Windows, una de ellas luego no se carga desde OS X porque Windows, en su maravilloso afán de poseerlo todo, ha decidido cambiar cierta cadena de las tablas internas del disco por “Microsoft Basic Data”. Hay que joderse con tomate. ¿No saben reconocer una partición ajena y no tocar nada? Pues parece ser que no, que tienen ganas de joder la marrana.

Bueno, la Utilidad de Discos de OS X se ve incapaz de recuperar la partición. Hala, nueva pérdida de datos. Cuatro máquinas virtuales y un montón de descargas.

***

Pues no, hay solución. Está aquí. Otro geek de la más alta alcurnia se ha encontrado con el mismo problema y ha creado una aplicación en Python para solucionar el problema. Lo único que hace es cambiar dicha cadena por su valor por defecto. Y entonces OS X reconoce la partición como suya y la monta.

Olé sus cojones.

Os cuento cómo hacerlo.

***

Desmonta el disco completo en donde esté la partición afectada. Luego graba el fichero gpt_surgeon.py en disco (ojo con grabar el html y no el contenido del mismo). Aquí viene cuando Apple piensa que somos imbéciles o así. Tu grabas un archivo, que te lo pone como texto de lectura escritura. Pero tu lo quieres de ejecución, porque si no ya puedes darle de sopapos porque se negará a correr.

Hay que añadir el bit de ejecución. ¿Cómo? Ahí está el problema. Desde la interfaz gráfica no se puede, porque CMD-I sólo te dejar cambiar entre lectura y escritura, pero no ejecución.

Quizás haya algún botón por algún lado para activarlo, pero no lo he encontrado, así que tienes que abrir una ventana de terminal y cambiarlo ala UNIX: “chmod u+x gpt_surgeon.py”. Claro, puede que algún imbécil siga la secuencia desde el Finder y sea capaz de cambiarle los permisos a un troyano. En fin, viva la ergonomía y usabilidad maqueras.

Luego sigues la secuencia explicada en el enlace de arriba:

  • ./gpt_surgeon.py list /dev/disk<n>, en donde <n> es el disco malo.
  • Localiza la partición jodida, en la que debe aparecer el infame texto de “Microsoft Basic Data”.
  • sudo ./gpt_surgeon.py repair /dev/disk<n> <y>, en donde <y> es la partición rota.
  • Al poco, OS X (o el script) montará todas las unidades, habiendo reparado la estropeada.

Y ya está, esta ha sido la crónica del día de hoy. Cagontó…

 

Bueno, una vez que hemos visto lo que hay dentro del nuevo Windows 8, y comprobado que WinRT no es un subsistema sino algo por encima de Win32 como es .NET, vamos a contaros las dos formas que hay de programar con C++ para la interfaz Metro.

Ya lo he comentado antes, pero voy a repetirlo aquí por mor de claridad. En Windows 8 hay dos escritorios diferentes. Por un lado tenemos el clásico de toda la vida que es prácticamente idéntico al de Windows 7, y por otro el de la interfaz Metro. Si no cambian las cosas, los equipos que lleven un procesador x86 tendrán acceso indistinto a los dos, mientras que aquellos que lleven procesador ARM sólo verán la interfaz Metro.

Eso quiere decir que habrá dos tipos de aplicaciones: las clásicas y las Metro. Las primeras sólo podrán compilarse para x86 (de 32 o de 64 bits) y sólo funcionarán en las máquinas Intel. Si estamos en la interfaz Metro y lanzamos una aplicación de este tipo, el sistema cambiará al escritorio clásico.

Las segundas podrán compilarse para x86 o para ARM y en ambos casos funcionarán en sus propios sistemas, pero siempre bajo la interfaz Metro. Es decir, si queremos que nuestra aplicación Metro escrita con código nativo pueda correr en los dos tipos de arquitectura, tendremos que proveer dos compilaciones.

Con .NET (C# y VB.NET) viene a pasar lo mismo, aunque en este caso creo que con especificar AnyCPU será suficiente para que la aplicación corra en ambas arquitecturas. Y de nuevo tendremos los dos tipos de aplicaciones: de escritorio y Metro, con las mismas reglas.

Por lo tanto, cualquier programa escrito en cualquier lenguaje que funcione ahora mismo en Windows 7, no debe tener ningún problema en ejecutarse en la siguiente versión, pero siempre en el escritorio clásico. Y podremos seguir escribiéndolos como hasta ahora.

***

Eso quiere decir que tenemos dos API diferentes e incompatibles entre sí. Por un lado tenemos el API de Win32 clásico y tradicional, sobre el que se construyen bibliotecas de terceros y el .NET. Aquí podemos meter VB6, Delphi, C#, C++/CLI, QT… Vamos, lo que hasta ahora.

Y para Metro hay una nueva API que se llama WinRT. Creo que hay cosas compartidas con Win32, pero no me hagáis mucho caso porque todavía no he visto nada. De todos modos si las hubiera, podemos tomarlas como si fueran nuevas, porque son excluyentes, al menos de momento.

Es decir, o bien desarrollas para Win32 o bien para WinRT, pero no puedes tener un ejecutable que use partes del otro más allá de las que MS ha querido compartir, y entre ellas no se encuentra C++/CX.

Por lo tanto también hay dos versiones de .NET. La de la interfaz Metro se construye sobre WinRT, y la clásica sobre Win32. Nos podemos hacer a la idea de que, aunque tengamos un API con nombres similares, por dentro funciona todo diferente (lo que no es cierto, pero a efectos prácticos sí que lo es, ya que las aplicaciones Metro deberán ir firmadas y el proceso de firmado garantiza que no vas a salirte de las API estándar -¿De qué me sonará eso?).

***

No obstante, WinRT no está escrito con C++/CX si no que está hecho con C++ clásico. Y en cierto modo es lógico, ya que no es más que una extensión a Win32, que es C y C++. Además, independientemente de mis diatribas personales, es algo bueno que le añada funcionalidad a un API que lleva tanto tiempo funcionando con regularidad y sin grandes problemas. Imaginaos los bugs que podría tener algo escrito desde cero.

Por lo tanto, podemos desarrollar aplicaciones para Metro sin usar .NET ni C++/CX. Podemos utilizar C++ y una biblioteca de plantillas llamada WRL (Windows Runtime Library), que viene a ser algo así como el ATL de Metro.

Microsoft no recomienda usarla, más que nada porque es compleja y porque de momento no hay documentación alguna sobre ella, pero está ahí, y es la base de Metro.

Si queremos echarle un vistazo, podemos acercarnos a “Program Files (x86)\Windows Kits\8.0\Include\winrt\wrl” y ver qué hay dentro. Tomaos un par de aspirinas antes.

Básicamente se trata de toda la infraestructura y parafernalia para acceder a los objetos COM y componentes de Metro.

***

C++/CX ocupa el nicho de lenguaje nativo para Metro, con lo que es más rápido que C# y que VB.NET, y es con el único con el que se puede acceder a DirectX (y por tanto a la creación de juegos). También es nativo. Es decir, que no es .NET y compila al código máquina que todos conocemos y de hecho es idéntico al C++ de toda la vida.

Lo que ocurre es que contiene una serie de extensiones que nos van a facilitar la vida a la hora de operar con Metro y sus componentes. Soporta clases parciales, se entiende bien con XAML e instanciar o crear un componente COM es un juego de niños comparado a como se hace con Win32.

Digamos que con esas extensiones nos ahorramos una buena faena a la hora de programar, y será el compilador el que sustituya esa azúcar sintáctica por el código necesario.

En siguientes entradas os contaré más sobre C++/CX.

Bueno, al final no ha costado mucho encontrarlo. Básicamente, el resultado de esta investigación es:

image

O con otras palabras: WinRT y Metro se ejecutan, como todo lo demás, sobre Win32, con las ventajas y los inconvenientes que eso pueda tener. No me malinterpretéis: no hay nada malo que la arquitectura sea diferente a la indicada en el gráfico de arriba, lo que está mal es que Microsoft nos mienta tan descaradamente. Simplemente eso.

Si lo han hecho así, por algo será y sus motivos tendrán, y es entonces cuando, ya definitivamente, yo tenía razón: Windows ya no es Windows NT, y su grandiosa arquitectura por bloques se ha perdido en el camino. Y esto sí que es malo, bastante malo, porque estamos volviendo a un batiburrillo de código como es, por cierto, el OS X (quizás algún día hable de ello).

Vosotros mismos podéis comprobarlo sin problema alguno y de forma muy rápida. Tenéis que construir dos aplicaciones, una WinRT en C++/CX y otra clásica de Win32. No hay más que utilizar las plantillas por defecto sin ningún cambio.

Eso sí, hay que hacerlo a partir de la versión Developer de 64 bits de Windows 8, e instalar una versión de la MSDN, porque la Express creo que no es capaz de generar programas Win32 puros.

He llamado “TestWin32” a mi aplicación tradicional, que genera una ventana de Windows normal y corriente utilizando directamente el API de Win32. A la Metro la he llamado “TestSplitApplication”. Una vez generadas, tenemos que compilarlas. Visual Studio se os quedará más o menos así:

image

Si ahora nos vamos a la carpeta en donde está almacenado el proyecto (que podemos hacer desde el mismo IDE posicionándonos en el nombre de la solución en el Explorador y elegimos Open Folder in Windows Explorer), carpeta Debug, encontraremos el ejecutable del programa nativo (TestWin32.exe) y dentro de la carpeta TestSplitApplication, el de la aplicación Metro.

(Por cierto, en uno de esos lapsus teclae tan habituales en mi, le he dado el nombre de “TestSplitApplicarion” en lugar del correcto.)

Ahora debemos conseguir el Dependency Walker, aunque existen otras herramientas de línea de comandos que nos permiten hacer lo mismo dentro del SDK, lo interesante es utilizar esta porque lo veremos todo de un golpe. El mayor problema es que se trata de una utilidad que hace tiempo que no se incluye en ningún SDK, por lo que hay que conseguirla de forma externa.

Una vez obtenida la versión de 32 bits, porque nuestros proyectos son de dicho tipo, la ejecutamos sobre cada uno de los dos programas. Este es el resultado:

image

¿Lo veis? Ambos programas importan las mismas DLL, las de Win32 como KERNEL32.DLL y USER32.DLL.

Es decir que ambos son aplicaciones Win32 nativas.

***

Si nos diera por abrir, por ejemplo, uno de los dos KERNEL32.DLL, veríamos que ambas DLL son la misma con las mismas dependencias y exportaciones. Por lo tanto, ambas aplicaciones dependen del mismo subsistema.

Reitero que es una tontería, pero no lo es cuando intentan engañarte.

Lo que sí parece han hecho ha sido romper KERNEL32.DLL en otros ficheros más pequeños que contemplan subconjuntos de lo que en versiones anteriores había en él. Quizás de esta forma reduzcan la huella de memoria evitando cargar sub ficheros cuando estos no se vayan a utilizar.

***

Esto nos lleva a un tercer problema: parecer ser que una aplicación Metro no puede ejecutar funciones de Win32, y una de Win32 tampoco de WinRT.

¡¡Pero si es el mismo subsistema!!

Pues bien, estamos ante una limitación artificialmente impuesta por Microsoft sin ningún motivo técnico aparente… con lo guapo que sería hacer aplicaciones Win32 con C++/CX…

Se me ocurren un par de trucos para poder forzar esto, pero no creo que valga la pena hacerlo en una versión tan temprana como esta. Quizás cuando salga la definitiva, si tengo ganas y si nadie más se me adelanta, lo intente.

image

Observad con detalle la imagen de arriba. Fijaos en que está dividida en dos grandes bloques. A poco que os haya preocupado la arquitectura lógica de Windows, os daréis cuenta de que hay nueva chica en la oficina: WinRT.

Ya hablé de algo así aquí, pero en relación con la arquitectura de Apple comparada con la de Windows, y de los últimos cambios que Microsoft ha ido haciendo para adecuar su plataforma NT para que sea funcional y útil para el usuario medio, dejando un poco de lado la arquitectura tradicional.

Pues bien, parece ser que me tengo que comer mis palabras con patatas (no, no esas patatas, Z). Volviendo al gráfico anterior, WinRT es un nuevo subsistema igual que lo es Win32. Para aquellos que no tengan claro qué es, os cuento un poco la arquitectura teórica de Windows NT.

El sistema operativo cuenta con un kernel (sí, como el de Linux, pero con muchas más cosas dentro de él y mucho más dinámico), que en teoría se asienta sobre una capa HAL que abstrae a dicho núcleo de la arquitectura física. En su momento hubo HAL para ARM y para otras plataformas. En la actualidad sólo la hay para x86, tanto en versión de 32 como de 64 bits.

O eso creía tras haber hecho un somero análisis de las tripas de Windows 7. Pues bien, si Microsoft añade soporte para ARM (y recordemos que van a salir procesadores de este tipo de 64 bits), dicha capa debe ser o bien reimplementada o bien ya existía y simplemente estaba inactiva. O lo que me parece más lógico: recompilar todo el sistema operativo para que se ejecute en dicha arquitectura, cambiando lo que haya que cambiar, dado que eso de traducir cualquier otro procesador a x86, sobre todo desde un ARM, suena a fantasía animada de ayer y de hoy.

Por otro lado, Windows se mueve mediante subsistemas. Uno de ellos es Win32. Otro lo fue OS/2 y también Posix (sí, en un pasado lejano, Windows NT era capaz de ejecutar comandos de unix con las primitivas de desarrollo que tiene la parte estándar Posix de Unix). Es decir, un subsistema suministra cierta abstracción sobre el núcleo, proporcionando un API mucho más rico y potente. Y de paso lo aísla para que las aplicaciones sean incapaces de tumbarlo.

En otras palabras, Win32 se ejecuta en el anillo 3 y el núcleo en el cero, y es Win32 el que, cuando una aplicación pide algún recursos del sistema (por ejemplo un puerto serie), el que se encarga de mover la petición y de realizar tareas intermedias, evitando así que un mal uso por parte de una aplicación genere una pantalla azul.

Digamos que una aplicación en el anillo 3 jamás podrá tumbar al sistema ejecutándose en el anillo 0, o al menos esa es la teoría. A veces un parámetro mal pasado puede terminar en una caída completa, pero no es lo habitual, y cada vez menos.

Pues bien, aparte de Win32, ahora tenemos un nuevo subsistema llamado WinRT. O eso dice, al menos la teoría y así nos lo presenta Microsoft en sus gráficos y en la escasísima información de la que disponemos.

Una de mis próximas tareas es la de intentar averiguar si esto es así o no lo es. No es la primera vez que Microsoft miente descaradamente, como cuando dijo de XAML no iba a necesitar de Win32 y que desaparecían los bucles de mensajes y que se ejecutaría sobre DirectX… Hasta donde sé, todavía eso no es del todo cierto.

También nos dijo que .NET iba a ser un subsistema, y realmente se ha quedado como una capa sobre Win32…

Por lo tanto, estad atentos al blog. Además, el dibujo original de Microsoft deja mucho que desear respecto a la claridad, presentando Internet Explorer y .NET como subsistemas independientes de Win32, lo que es, a todas luces, completamente falso:

image

***

Volviendo al gráfico de arriba, podemos ver algunos detalles que creo no son del todo ciertos, pero nos dan una idea de la arquitectura del nuevo WinRT (sobre la que se basa la interfaz METRO que llevará, junto al escritorio tradicional, Windows 8).

(Una de las cosas por las que dudo que WinRT sea un subsistema completo es el hecho de que Windows 8 consuma menos memoria que el 7 y de que se pueda producir ese intercambio tan rápido entre los dos escritorios, lo que me hace pensar que, de nuevo, se trata de algo sobre Win32).

En WinRT hay dos interfaces de desarrollo principales: XAML y HTML. Es decir, podemos hacer aplicaciones clásicas basadas en el primer modelo y modernas en el segundo.

A simple vista puede parecer que en ambas se utiliza una misma variación del XML, pero no es así. En el caso de HTML/CSS nuestra aplicación no será otra cosa más que una página web ejecutándose dentro de una sesión más o menos oculta de Internet Explorer. Tendremos acceso a esas dos tecnologías (incluyendo HTML5) y JavaScript como lenguaje de desarrollo.

En el caso de XAML, estamos ante la última evolución de las interfaces de usuario dinámicas en las que la interfaz está completamente (o lo más posible) separada del código en sí, lo que permite una soltura nunca vista hasta ahora. O al menos esa es la teoría y casi os diría que la práctica.

XAML es muy potente. Demasiado, casi diría. Se trata de una especie de colección de contenedores jerárquicos que pueden actuar como tales o como elementos finales, y pueden mutar de un tipo a otro con una facilidad pasmosa. De hecho, cambiar el aspecto visual de una aplicación XAML puede llegar a ser cosa de unas pocas –muy pocas- líneas de código, con el añadido de que quien haya desarrollado con .NET y la versión anterior, está casi listo para esta nueva (que por cierto no es mi caso, pese a ver en su momento las ventajas evidentes del nuevo modelo).

Por lo tanto, los programadores de .NET que hayan abandonado Windows Forms por la nueva forma, lo tendrán bastante fácil. Los dinosaurios como yo mismo tendremos ciertas dificultades en adaptarnos… o no.

¿Recordáis C++/CLI, el C++ del .NET? Pues bien, la única pega para que dicha extensión de C++ pudiera utilizar XAML es que no se soportan las clases parciales como en C o en VB.NET. Por desgracia, eso sigue siendo así, y la interfaz clásica continua estando vedada para los programadores de C++ en .NET, quedando limitados a Windows Forms y a un IDE que no es que se muestre muy estable manejando el lenguaje…

***

Bueno, ahora, por fin, entra C++/CX. ¿Qué es? Nada más y nada menos que una nueva extensión a C++, con una sintaxis muy similar a C++/CLI pero con un propósito muy diferente: el de soportar METRO y XAML. Y no, no es .NET. Es nativo.

Supongo que Microsoft se planteó ante una disyuntiva muy pero que muy gorda: el rendimiento de .NET es suficiente para un PC, pero no lo es para una plataforma móvil como una tableta. No estoy diciendo que sea malo, estoy diciendo que eso de tener una máquina virtual consumiendo memoria y recursos, un jitter ejecutándose detrás de todo, y un post-compilador pasando MSIL a código nativo no es de recibo para un Tablet.

Delante de todos está el fracaso de Android. Por favor, absteneros fundamentalistas y otros pájaros de similar calaña: Android es un fracaso. Puede que aguante unos cuantos años, pero terminará por caer estrepitosamente, tanto por problemas técnicos (demasiado consumo de memoria, demasiada lentitud, demasiadas capas una encima de otra, demasiadas caídas) como por comerciales (demasiada fragmentación, demasiado abandono de terminales a medio hacer), etc..

Por lo tanto, para competir en igualdad de condiciones, tenemos que darle caña a iOS. Se debe hacer algo similar, y ese algo es WinRT y C++/CX. No hay máquina virtual .NET, ni nada oculto (o eso quiero creer), tan solo un motor de ejecución, una interfaz y el propio sistema operativo. O en otras palabras: objetive-c, cocoa y lo que quiera que haya en el núcleo de iOS (parece ser que un BSD recortadito).

Otro problema es la arquitectura. Ya se ha demostrado que x86 es demasiado pesado y demasiado hambriento de energía como para ser útil en el mercado móvil, por lo que hay que subirse al carro de ARM, que son micros mucho menos complejos y por tanto consumen mucho menos y andan más sueltos.

Por lo tanto se necesita algo diferente, algo mucho más liviano. Y eso, de nuevo, es WinRT. Por lo tanto, la combinación ganadora es C++/CX, XAML y, cómo no, C# y VB.NET corriendo sobre una variación de .NET llamada .NET 4.5 WinRT (y que funcionará más lento y consumirá más batería que una aplicación realizada con C++/CX).

Pero el núcleo, el centro de todo, es C++ y WinRT. Luego está .NET, encima igual que en Win32. Como debe ser. Y de nuevo absténgase fundamentalistas. Si lo han hecho por algo será. Quien cae del árbol a tiempo todavía puede recuperarse.

***

C++/CX no es .NET. Es nativo. Y la parte CX no es más que un envoltorio cómo para los interfaces COM, ese animal mitológico con el que los programadores de C++ nos tenemos que enfrentar de tiempo en tiempo y que nos pone los pelos de punta.

Es decir, la parte CX sólo se utiliza para interactuar con XAML y los componentes que se hayan creado a tal efecto. Luego, nuestro código será C++ normal y corriente, con la STL, los streams (que personalmente pienso que no son muy útiles), Boost o lo que queramos usar y esté disponible. Desarrollo determinista por completo, sin recolector de basura (a no ser que nos hagamos uno), sin elementos ocultos excepto el envolvente COM que han llamado CX y que nos servirá para interactuar con los componentes.

Otra ventaja de C++/CX sobre .NET es que, si quieres hacer un juego sobre DirectX, tendrás que usarlo ya que ni C# ni VB.NET están soportados, de nuevo como debe ser.

Ah, y con soporte para clases parciales, lo que… bueno, mejor lo dejamos para más adelante.

Ñas. Por fin lo he leído. Más de un año para acabarlo. Entre lo que os conté con mi jefe y la empresa, y cierto bajón existencial, dejé de leer temas técnicos, pero creo que he vuelto, o eso espero.

Bueno, al rollo.

Lo primero de todo, y pese a que me vais a llamar de todo, el libro no me ha aportado nada nuevo, salvo quizás en los últimos capítulos cuando habla de integraciones y manejo de grandes grupos de programadores, entre los que no me cuento. Es decir, o bien programo solo o bien en pareja o para un tercero, haciendo rutinas de bajo nivel o bibliotecas (DLL, como las llama mi jefe).

Lo único ha sido la sorpresa de encontrar veinte años de experiencia condensados en un solo libro. Y lo que falta, que no es poco. Pero bueno, lo cierto es que este libro tienes que leerlo.

Si no lo has hecho, cómpralo y ponte a ello, porque seguro que te va a resultar constructivo. Y si te dice cosas nuevas, vuélvelo a leer cada año o cada seis meses. O si eres de los que va despacio, cuando termines por una punta, cógelo por la otra.

Es increíble lo que pueden dar ochocientas páginas, pero lo dan.

Te pego una cita, sacada de aquí:

 

Si sólo tienes oportunidad de leer un libro sobre desarrollo de software en toda tu vida, procura que sea éste. Code Complete es prácticamente la biblia del desarrollo de software, además de una de las mejores guías prácticas sobre la programación de todos los tiempos. Es un libro muy fácil de leer, entretenido, y tremendamente práctico, con montones de recomendaciones útiles para cada fase del ciclo de vida del software. El simple hecho de leerlo te hará mejor programador. Seguro.

 

Con eso creo que basta.

Me he quedado poco menos que estupefacto con esta entrada del blog de SomaSegar. Y no, no penséis mal, que no es malo.

Básicamente viene a decirnos que está disponible la CTP de “Roslyn”, que según entiendo es una extensión -de momento- a Visual Studio 2010 SP1. De hecho nos la podemos bajar y jugar con ella.

Comienza diciendo que los compiladores se han venido haciendo en C++ nativo, pero que ya es hora de cambiar y que han rehecho los compiladores de C# y de Visual Basic desde cero en… Visual Basic.

Hay que joderse. La primera en la boca. ¿Pero no decían que el compilador y el propio .NET estaban hechos en C# (lo siento, no encuentro la referencia)? Ahora no, ahora resulta que C# está escrito en C++.

Y la segunda, también: C# está hecho en Visual Basic.

O están tontos, o yo no me entero, o mienten más que hablan. Para nada me extraña de que hubieran mentido en lo de hacer C# en C++, de hecho es lo lógico y coherente, ¡pero construirlo todo en VB?

De todos modos dejemos esto aquí, corramos un estúpido velo, y centrémonos en el meollo del artículo: compilador como servicio.

Es decir, en Visual Studio 11 los compiladores de C# y VB no serán ejecutables, sino servicios expuestos al público (espero que haya uno para invocarlo desde la línea de comandos), de modo que cualquiera podrá compilar.

No solo eso, sino que dejarán de ser una caja negra que, a partir de un código fuente, genera una salida compilada, sino que podremos acceder a los diferentes estados del proceso de compilación, e incluso podremos realizar solo unos pasos, como análisis semántico o la obtención del código IL (ensamblador del .NET).

Eso posibilita la creación de scripts en una consola interactiva. ¿Recuerdan la consola aquella que tenía el Visual FoxPro que permitía ir encadenando comandos como si programáramos? Pues lo mismo, pero en VB y en C#. Vamos, que reinventan la rueda.

En la entrada original hay un par de imágenes enseñando lo que puede hacer.

 

Cuando uno está en esto del switching indeciso, que no sabe si irse para Pinto o para Valdemoro, le pueden pasar cosas como la que os voy a contar.

Todos sabéis que desde hace unos años Apple permite la ejecución de Windows sobre su hardware compatible, y que suministra no sólo los drviers (que funcionan cojonudos), sino las herramientas necesarias para tener un arranque dual sin mucho problema. Por tener, hasta tenemos soporte de lectura para el formato de ficheros HFS+, con lo que veremos sin problemas las unidades del MAC, aunque no podremos escribir en ellas.

Una suposición personal es que, así, no podremos trastear en un sistema de ficheros en el que es peligroso tocar si no está cargado el sistema operativo. (Lo que viene a ser igual que con Windows, ya que si tenemos arranque dual, la instalación que no se haya iniciado podría ser fácilmente estropeada por algún zarpas, léanseme: yo mismo.

Pues bien, hasta aquí todo perfecto.

Supongamos ahora que queremos soporte de escritura. Porque somos así de chulos y así de molones, porque nosotros lo valemos. O simplemente porque tenemos una unidad de disco externo con nuestro MAC que también queremos usar en Windows.

Vale, la formateamos con FAT32 y listo. No os lo aconsejo. Aparte de que es un sistema de ficheros no muy robusto, carece de sistema de permisos y tiene otras limitaciones en cuanto a los nombres de los ficheros. Y si encima tienes ya ocupados unos cuantos gigas, como que se hace cuesta arriba la conversión.

¿Podemos escribir en HFS+ desde Windows? La respuesta corta es que sí. La larga es que mejor no lo hagas. Me explico.

Paragon Software Group cuenta con un driver para Windows (tanto de 32 como de 64 bits) que permite eso mismo: leer y escribir sin problemas sobre particiones HFS+. O eso dicen.

En mi caso ha sido un desastre total. No sólo me ha jodido la partición donde estaba el OS X (que no tendría mayor problema) sino que también ha destrozado otra sobre la que no estaba escribiendo, alojada en un disco externo por FireWire 800.

Me tocó reinstalar el OS X desde el DVD de Lion (porque de paso borré todo el disco interno del iMAC e hice una instalación limpia para ver si se me iban los problemas al actualizar a la 10.7.2) y olvidarme de los datos que había en el disco externo, algo así como medio Tera en máquinas virtuales, ISOs descargadas y otras copias de seguridad…

Así que ya sabéis, tomaos con calma el “HFS+ for Windows” y probadlo extensamente antes de pasar a producción.

¿Sabéis lo que es iCloud? Aunque digáis que sí, me juego un gallifante a que no. ICloud es una mierda envuelta en papel brillante, un trozo de bisutería rodeado de oro del que cagó el moro.

Acabo de comprobarlo. Tengo dos iMAC, un iPad, un iPod y un iPhone (este del curro, que todavía no he actualizado).

Como sabéis, hace unos días salieron todas las actualizaciones de golpe, tanto para el escritorio como para los dispositivos móviles. En mi caso la actualización a Lion 10.7.2 se realizó sin problemas, salvo una notable ralentización del sistema una vez reiniciado, ralentización que parece es temporal ya que ahora funciona todo casi igual de rápido que antes… excepto algún que otro rosetón multicolor de la muette que deja mi i7 de cuatro núcleos dobles y 12 GB de RAM como autista unos segundos… Eso no lo hacía antes de aplicar el parche.

No obstante, la actualización de los dispositivos móviles ha sido más que penosa. En primer lugar falló la descarga y la actualización. Me dio el infausto “internal error” causado por la caída de los servidores de Apple. Hay que joderse, con la expectativa generada y que la empresa no fuera capaz de preverlo con antelación. Joder, hasta Microsoft, el denostado Microsoft, cuando saca un producto nuevo que es muy esperado, aumenta y confía en terceros para las descargas…

Pero no todo termina ahí, no. El iPod se actualizó más o menos bien, a la tercera o la cuarta, pero el iPad hubo de sufrir bastantes intentos. O bien se quedaba autista o bien simplemente fallaba. Como tengo casi 40 GB de datos en él, y la interrupción se producía casi al final, la cosa llevaba su tiempo. Al final, restauración de fábrica, instalación de las aplicaciones y vuelta a meter los datos. Menos mal que soy un chico previsor y los tengo en el MAC, listos en sus carpetas. Eso sí, todavía estoy configurando programas…

¡Quietos parados, fanboys! A ver. Uno mete el iPad, te dice que tiene una actualización, le dices que sí, y a medias falla. No hay otra. No es mi culpa. Es de Apple. Por el motivo que sea. Mi iPad está impoluto, sin Jailbreak, sin cosas raras. Ya que está todo cerrado, debería funcionar a la primera, porque si no me vuelvo a Windows que me deja hacer lo que quiera sin más, y si falla puedo achacarlo a mi ineptitud, no a la de Apple. [Como colofón a esto, no soy el primero que ha tenido problemas. Básicamente la actualización a iOS 5 ha sido pésima. También quiero pensar que no se trata de un intento de que estampe mi iPad 1 contra la pared y me compre un 2.]

***

Bueno, ahora sí, ahora hablemos de la magia de la cosa esa del iCloud. ¿Os pensáis que es una versión mejorada de Dropbox? Juas, ni se le acerca. Hasta el infausto SkyDrive de Microsoft es mejor.

No, no es que vaya mal, es que no cumple mis expectativas. Es una decepción total, más que total, humillante. Lo único que te va a guardar iCloud son los documentos de Pages, de Office (a mi no me lo hace), tus fotos y los calendarios… pero los que crees en la nube. Es decir, la cacareada sincronización sólo se va a producir entre los documentos políticamente correctos que, como siempre, le vengan en gana a Apple. No mis documentos. No mis fotos ya hechas, no los documentos que yo quiera, no.

Y encima, como elemento de obsolescencia programada, si quieres tus documentos en la nube, paga por nuevas versiones que lo soporten. Asco me da. Decepción. Tristeza.

***

En serio, tengo una extraña sensación que me parece que, conforme va pasando el tiempo, es más fuerte y coherente: cuanta más cuota de mercado coge Apple, más se parece a los peores tiempos de Microsoft, con fallos estúpidos, dejadez en atender los requisitos de los clientes y olvidarse de que uno debe estar al loro con las actualizaciones de seguridad y que no debe esperar dos meses a, por ejemplo, invalidar una entidad certificadora. Es una especie de deja-vu, una sensación como de inquietud y de malestar… Ahora que Jobs ya no está, quizás la cosa mejore… aunque lo más seguro es que empeore.

Básicamente, maldita la hora en que me pasé a Apple.

Ya os comentaba en otra entrada del blog algo sobre la nueva biblioteca de paralelismo masivo llamada C++ AMP que traerá la nueva versión de Visual Studio, que ahora, tras el lanzamiento BUILD de hace unos días, se llama Visual Studio 11. Eso no quiere decir que vaya a salir este año, sino que se trata del número de versión. Si Visual Studio 2010 era la 10 (una mera coincidencia), la 11 quizás salga en 2012, más o menos cuando Windows 8.

 

Una pequeñísima introducción sobre C++ AMP

Es una biblioteca de C++ escrita para poder ejecutar código paralelo de forma independiente del hardware y a la vez aprovechar el hardware actual de los PC (léase procesadores multi núcleo y tarjetas de vídeo 3D) sin tener que complicarnos mucho la cabeza. También está pensada para aprovechar los futuros desarrollos de forma transparente para el programador.

También forma parte de Visual C++, por lo que no es necesario nada extra, y se encuentra perfectamente integrada en el producto, por lo que las tareas habituales como compilación y depuración son transparentes para el usuario.

Tan sólo necesita una extensión del compilador de C++ (el famoso restrict del que os hablé en la otra entrada), tiene una sintaxis similar a la de la STL, y es muy fácil trabajar con vectores multidimensionales de forma independiente del hardware.

Para los que no lo sepáis, una de las limitaciones de los procesadores SIMD (Single Instruction Multiple Data), que parafraseado podría ser Una Sola Instrucción Para Muchos Datos, está en su limitación respecto al tamaño de los arrays que pueden ejecutar de una sola tacada. Es decir, imaginaos que tenéis que rotar un cuerpo 3D compuesto por X polígonos. La rotación se puede hacer con una sola instrucción ejecutada para cada uno de los polígonos. Algo así como un bucle for que recorra todos y cada uno de ellos, aplicando la misma transformación. Con un SIMD, uno carga los datos en cada pipeline (o como se llame) y luego ejecuta la instrucción sobre todos ellos a la vez. El problema viene cuando tienes más polígonos que pipelines, y tienes que hacerlo a pedazos. Añade que el tamaño de cada pedazo no solo es diferente para cada procesador SIMD, sino también para cada versión (SIMD=Tarjeta de vídeo 3D). Con esta biblioteca te olvidas de todo eso. Ya lo hace ella sola.

Está basada en DirectCompute, una ampliación añadida a DirectX 11.

 

¿Puedo ejecutar C++ AMP?

Una opción es instalarte todo el tema (compilador, Direct X, etc) y probar a ejecutar un programa. Otra más sencilla es bajarte el programa que se describe en esta entrada y ejecutarlo. No requiere nada especial, y no usa C++ AMP para determinar si tu hardware lo permite o no.

En mi caso, ni el PC del curro, ni la máquina virtual, ni el portátil lo soportan. Pero sí mi PC principal, y seguro que el iMAC con Windows 8 instalado, que va a ser una de mis próximas tareas.

De todos modos, si el programa te dice que NO tienes hardware, no te preocupes, ya que la instalación del SDK de DirectX 11 o de Visual Studio 11 te creará un dispositivo emulado que no va a funcionar muy rápido que digamos, pero que al menos te permitirá ejecutar los programas.

Para aquellos vagos que no quieran leerse la entrada, o que simplemente no sepan inglés, aquí está el programilla.

 

Usando C++ AMP

Necesitas tener Visual Studio 11 en algún Windows (incluyendo la versión 8). Usar esto es tan fácil como incluir amp.h y añadir el espacio de nombre concurrency en tu proyecto. Ya está, ya puedes escribir código funcional.

Uno de los ejemplos más sencillos (y afuncionales) podría ser:

 

#include "stdafx.h"

#include <amp.h>

#include <iostream>

 

using namespace concurrency;

using namespace std;

 

int _tmain(int argc, _TCHAR* argv[])

{

cout<<acos(0.123456)<<endl;

return 0;

}

 

Lo que a todas luces sirve para poco pero nos permite ver que todo funciona bien, ya que la función acos viene dentro del espacio de nombres concurrency como podríamos comprobar si escribiéramos

concurrency::a

 

Y dejáramos al sistema de IntelliSense que se abra y nos muestre las funciones disponibles.

 

Más ejemplos

Un buen sitio para aprender más sobre esto, en pequeñas dosis, es el blog de Parallel Programming in Native Code, que es de donde yo he sacado todo esto. De todos modos, en esta entrada del citado blog tenéis algunos puntos de entrada: C++ AMP in a nutshell.

Otro ejemplo, que de momento no he podido ejecutar porque lo he compilado con Visual C++ 11 en un Windows 7 virtualizado, es el ejemplo del SDK de DirextX llamado “N-Body Simulation Sample” y que ha sido portado aquí.

con no comments
Archivado en: ,,
Más artículos < Página anterior - Página siguiente >