Uniones en C#

Hay veces que uno no encuentra lo que busca, y cuando no lo está buscando, lo encuentra. O algo así. El hecho está en que empecé a hacer una pequeña utilidad interna en C# que necesitaba bastantes estructuras y encima con campos repetidos.

Eso en C++ es fácil de solventar. Un se crea una jerarquía de estructuras igual que podría hacerlo de clases, y listo. Es decir, si yo necesito tres estructuras diferentes que tengan, por ejemplo, varios campos del mismo nombre y tipo, lo más fácil es crear una estructura base y heredar de ella. Algo así:

struct Base
{
    string Nombre;
    string NombreAlternativo;
};

struct Casa:public Base
{
    string Dirección;
};

struct Coche:public Base
{
    string Propietario;
};

De este modo ahorro escritura, ya que tanto la estructura Casa como Coche tendrán los campos Nombre y NombreAlternativo sin haberlos tenido que teclear. Suena un poco trivial pero cuando tienes diez o doce estructuras lo agradeces, incluso de esta forma te evitas los errores de tecleo y pones en una de ellas un campo con “Nonbre” en lugar de Nombre.

Eso en C++, en C# llega uno tan contento, se pone a picar código y… ¡ñas, no deja! El compilador protesta como un loco…

Me voy a la ayuda y, efectivamente, una limitación más del .NET: pese a que ellas mismas heredan de ValueType e indirectamente de Object (por cierto realizando una metástasis muy extraña y pasando de ser un tipo-referencia, como es Object, a un tipo-valor…)

Pero sigo leyendo para abajo y me encuentro con una sorpresa, y es cómo hacer uniones aprovechando los atributos.

El tema está aquí, y básicamente viene a decir, en la sección “Attributes on Structs”, que utilizando los atributos “LayoutKind.Explicit” y “FieldOffset”, podemos definir el punto de inicio de cada elemento de la estructura de forma manual.

Veamos un ejemplo muy socorrido en C/C++ en relación a las direcciones IP, que todos hemos manejado alguna vez. Una dirección IP se puede ver como un entero sin signo de 32 bits (que es como las ve el software) o como cuatro números situados entre 0 y 255. Esto en C/C++ se puede expresar así:

union IP
{
    __int32 As32bits;
    unsigned char asBytes[4];
};

Para referirnos a ellas, podemos usar ambas partes y ambas serán el mismo valor:

IP miIP;
miIp.AsBytes[0]=192;
miIp.AsBytes[0]=168;
miIp.AsBytes[0]=1;
miIp.AsBytes[0]=1;

Y como miIP.As32bits tendremos en valor equivalente.

Pues bien, en C# esto se puede conseguir más o menos así:

using System.Runtime.InteropServices;
[StructLayour(LayoutKind.Explicit)]
struct IP
{
    [FieldOffset(0)]
    Public Int32 As32bits;
    [FieldOffset(0)]
    Public byte a;
    [FieldOffset(1)]
    Public byte b;
    [FieldOffset(2)]
    Public byte c;
    [FieldOffset(3)]
    Public byte d;
}

Y podríamos acceder a ella tanto asignando los valores a, b, c, d como As32bits. También podríamos añadirlo como un array, pero eso queda de ejercicio de clase.

(NOTA: La entrada está escrita sin comprobar el código, por lo que podría haber algún gazapo. De todos modos, la esencia del código es correcta.)

¿Soy Bill Gates o le envío el currículum? :-)

Que nadie se me altere y piense que se me ha terminado de subir el pavo a la cabeza, o que se ha roto el fino hilo que me separa de la locura más espantosa… más que nada porque ya se me rompió hace tiempo. 😛

Todo viene a cuenta de la siguiente entrada en el blog de Marino Posadas en Geeks. El título de la misma es “The Art of Computer Programming o cómo resistir el paso del tiempo”, y comenta el hecho de que todavía esos libros, pese a tener casi cuarenta años de antigüedad, siguen completamente vigentes…

En la entrada también comenta lo que Bill Gates escribió en su blog sobre la obra, y era que él no había podido pasar de la página 40 pero que la exigía a sus ingenieros.

Pues bien, yo llevaba ya varios años con el gusanillo de conseguir los libracos pero no tenía cómo comprarlos ya que en la Web de Amazon proliferan versiones, ediciones y empaquetamientos. En los comentarios de su entrada, Marino vino al rescate de uno y al final tuve claro qué comprar y, para no perder fuelle, lo hice.

En concreto necesitas tres compras para obtener todo lo que se ha publicado hasta ahora:

  1. Los tres volúmenes en caja. Tercera edición de los dos primeros y segunda del tercero.
  2. Los cinco fascículos que componen el cuarto volumen.
  3. Un fascículo extensión al volumen 1.

Con eso, si he interpretado bien a Marino, lo tienes todo.

***

Bien, ahora entramos en materia. Esta mañana me han llegado, entregados directamente por la gente de Correos, como un par de semanas antes de lo previsto. Y eso que dicen que Correos es malo.

Ahora tan sólo me queda ver si soy un Bill Gates (es decir, soy incapaz de pasar de la página 40) o si puedo optar a enviarle el currículum…

¿Opináis vosotros lo mismo que yo? Pero claro, yo no tengo tanta pasta como él. Lo sabréis, dios mediante, aquí. (No creo que muy pronto porque la lista de pendientes por leer es grande, pero lo mismo me lío la manta a la cabeza. Total, no creo que me lleve mucho tiempo leer 40 páginas…).

Algunos bugs del Compact Framework

No llevo ni mil líneas de código de un nuevo proyecto embebido en C# y ya me he encontrado con al menos cinco bugs. En su momento abandoné C# para escritorio porque era un juguetito que apenas daba de sí para realizar aplicaciones de sistemas medianamente complejas. El mayor problema estribaba en que como te salieras de lo que los sabios habían determinado, aquello no funcionaba ni para atrás. Cosas que fallaban, muchas. Las más flagrantes eran serios problemas con los constructores estáticos, agravados en el caso de que se produjera una excepción dentro de ellos, excepciones que no se lanzaban cuando debían, y un largo etcétera en relación a elementos de Windows Forms.

Tengo constancia de que muchos de esos problemas han sido solucionados con los distintos Service Packs que le han ido saliendo a la versión 2.0 del .NET Framework, y pensaba que ya que el Compact también lleva unos cuantos, no tendría problemas con él.

Pero no es así en relación al Compact. Fijaros que no estoy hablando del 3, ni del 3.5, sino del 2.0, que lleva una buena porrada de años en la calle y que ya debería funcionar medianamente bien. No quiero yo ver la porquería que serán el 3 y 3.5 (recuerdo haber encontrado y reportado 5 bugs en una única sesión de media hora de jugar con ellos, de los cuales la mayoría serían resueltos en next version, que es la forma políticamente correcta que tiene Microsoft de quitarse a los pesados de encima y decirte con buenas palabras que no lo van a solucionar).

Los más triviales del Compact 2.0 se encadenan en torno al componente Tab Control, y básicamente tienen que ver con el tamaño del mismo y la posición de las páginas. Hablamos del .NET Compact Framework 2.0 con todos sus parches en compilación AnyCPU, no de la versión de escritorio.

Cuando el componente es más grande que la ficha y sale por debajo porque está anclado por arriba a la misma, .NET dibuja una barra de desplazamiento vertical que permite contener el componente completo. Sin embargo, si la anclamos por debajo, la barra de desplazamiento no aparece, y entonces los controles que haya en la parte superior ocultos a la vista no serán visibles.

El siguiente también tiene relación con este, y se presenta de forma aleatoria (o al menos yo no he sido capaz de poder reproducirlo siempre). El control no se redimensiona. Ya puedes ponerle el Width o el Heigth al valor que quieras, que él seguirá con el que tenga en tiempo de diseño. Parece estar relacionado también con el tipo de anclaje y de dock, pero no estoy seguro.

El gordo. Este problema clama al cielo, es para llorar, ya veréis. Crea un proyecto embebido en C# para Windows CE con el asistente y para el Compact 2.0. Añade un PictureBox al Form. Clica en la propiedad Image y carga un fichero JPG. Una vez hecho esto deberemos estar viendo la imagen en tiempo de diseño. Ejecutemos sobre un emulador o sobre un dispositivo real.

¡Tachán! Excepción al canto, la imagen no aparece por ningún lado. Os adjunto una imagen, para que veáis que no hay trampa ni cartón:

image

A la izquierda está el editor abierto por la excepción y mostrando esta, del tipo “Exception”. A la derecha está el Form mostrando la imagen, y más a la derecha el emulador.

Para más inri y jocosidad (aunque es para llorar), el tipo de excepción es “Exception”, así, a pelo. No del tipo recurso no encontrado, ni fichero no encontrado, ni nada de eso. Simplemente una “excepción”.

Pero todavía hay más, porque al menos en Windows CE te salta la excepción, en Windows Mobile, por ejemplo, simplemente falla, sin disparar ningún tipo de excepción ni nada.

No os vayáis, porque ¡sí, hay más!: incluso poniéndola a mano como un recurso normal, luego en el ejecutable ¡no hay imagen! Es decir, que lo que quiera que haga de linker en el C# pasa olímpicamente de este tipo de recurso.

¿Es para llorar o no? Pues eso, que se le quitan a uno las ganas.

V2.0

Bueno, lo de arriba fue escrito y programado para que se publicara el 21 de abril, ya que tengo entradas preparadas hasta esa fecha, pero resulta que mientras llega el citado día, seguí con el tema a ratos, porque no es un proyecto del curro, sino personal. Si lo contado hasta ahora clama al cielo, no os digo ya lo que viene a continuación.

Unos días después de desistir con el tema, vi el dispostivo con Windows CE por encima de la mesa y me dije que iba a reintentarlo, y así lo hice. Conecté el aparato (un JE200 vuelto a convertir en un cacharro CE puro para los curiosos) y para escarnio y befa personal, ¡funcionó a la primera! Bueno, no realmente, porque para evitarme la descarga de todo el Compact sobre el dispositivo, y sabiendo que él traía ya una versión 2.0, desconecté la opción de cargar siempre la última versión en el aparato/emulador.

Y entonces funcionó. O en otras palabras, la imagen se embebió en el ejecutable y este funcionó perfectamente. No obstante, había ahora un nuevo problema: el color de fondo de los botones no se cambiaba por el que yo había decidido (suma bug y sigue).

Me da por probar en un emulador de Windows Mobile 2003 y funciona todo perfecto, incluso lo de los botones. De vuelta al emulador del CE, me dice que el .NET instalado es muy viejo. ¿Cómo que muy viejo? Si lo que pasa es que no hay .NET (Si lo sabré yo que . Otro más al cesto.

Para resolver lo anterior, reactivo lo de bajar la última versión del Compact, lo hizo, cargó y funcionó, aunque el tema de los botones siguió sin funcionar… Lo cierto es que funcionó sólo la primera carga. En la demás ya dejó de hacerlo. Suma y sigue.

Bueno, al final, resumiendo: tras al menos dos Service Packs y varias “actualizaciones de seguridad”, el Compact no sólo es la misma mierd@ que antes, si no incluso peor, con regresiones que ni siquiera estaban presentes en la RTM.

Personalmente se me cae la cara de vergüenza ajena con esto, lo que reafirma y confirma algo que he dicho por aquí no hace poco: los test no valen para nada. Y me da para otra entrada sobre este tema que ya estoy empezando a barruntar. Permaneced atentos.

Desarrollando para el iPad

Como no es una entrada técnica ni de lejos, y está más relacionada con los libros electrónicos que con otra cosa, la he puesto en mi blog de Kindle Man.

La parte más interesante desde el punto de vista de este blog de Geeks es la parte final, en donde expongo, con palabras de la calle, una idea sobre un visor de ficheros por capas que quizás algún día implemente.

No obstante la primera parte también podría seros interesante porque da unas breves indicaciones sobre qué es lo que hay que hacer para poder publicar tu programa en la tienda de Apple.

Emulator image for develop with JE100/JE200 and other Windows CE 5.0 Devices

I’ve just created an ARM Windows CE 5.0 Emulator image and SDK that mimics the JE200 hardware and has some other useful additions like a Command Line console and other network tools. This emulator has some advantages over the old offered by Microsoft: it is an arm4i emulator that integrates into new Visual Studio way of manage emulators. Old one is a Virtual PC x86 emulator that cannot be integrated into new VS versions.

To work with this you need:

  • My Image Emulator that you can download from here.
  • Visual Studio 2005/2008 Standard or upper (Express versions does not work). I recommend Visual Studio 2008SP1.

The only restriction I impose is that only non commercial development can be done with this image. It has been made with a Platform Builder legal copy owned by the company I work for. Then I can add any reasonable feature you will want, but only for homebrew, Open Source or free programs.

To install this image you need to follow the next steps.

  1. Have a working Visual Studio installation.
  2. Deactivate UAC and restart if you are using Vista or Windows 7. Don’t be afraid, once installed you will reactivate UAC. This is caused by a limitation in the installer, which has a script that fails silently if UAC is active. Does not matter if you have accepted UAC elevation in program installation: the script fails.
  3. Install the SDK with a full installation.
  4. Restart your computer.
  5. Launch Visual Studio. Close Visual Studio (this is to force any pending script upgrade).
  6. Activate UAC.
  7. Restart your computer.
  8. Done! Now you have a new Device in your Visual Studio that says “WindowsCE5Emulator”.

Now, the best way is to test the image. Open Visual Studio, go to “Tools -> Connect to device” and select “WindowsCE5Emulator” Platform. In Devices select “Windows CE 5.0 Emulator” and click in “Connect” button. After some seconds you will have a Windows CE emulated session with a Windows Mobile screen size and in the “Connecting” dialog box you will see “Connection succeeded”.

That is!

In the Devices list you can see two devices: the one described and other called “Microsoft DeviceEmulator: ARMV4I_Release” and if you try to use that device it won’t work. It is for Microsoft eMbedded Visual C++ 4sp4 and older Visual Studio versions that connect via TCP/IP layer and we can ignore it.

Some customizations for JE100/JE200. Once we have the emulator installed, we can customize it to obtain a device like the JE100/JE200. We need to open Visual Studio and go to “Tools -> Options” and select “Device Tools”, open the tree and click in “Devices”.

Now open the combo “Show devices for platform” and select “WindowsCE5Emulator”. Select “Windows CE 5.0 Emulator” and click “Save as…”. Type a useful name like “JE200 Emulator”. Now we have 3 emulators available.

Select the new one, click in “Properties…” and be sure that “DMA Transport” and “Device Emulation Startup Provider” is selected. Now click in “Emulator Options…” and you can personalize it. For example, to mimic a JE200, you need to select “Specify RAM size” in “General” tab and type 64. Go to Display tab and select “Video” option and type 480 as screen width, 800 has screen height and 16 to color depth.

You need to specify 16 bit color depth because an emulator software limitation: the video memory is limited to 1 MB. It seems there is a hack to avoid this but it is untested and you need to mess in depth source code of Windows CE.

And finally you have a device emulator similar to JE100/JE200. Of course you can specify and play with any screen size or any other characteristic that will offer the emulator. And as it has a persistent registry you can copy the JE files and have exactly the same device, but then you need to save your personalization.

Hemos leído: VVAA: Beautiful Code

Book cover of Beautiful Code

Algo desilusionado sí que he quedado. No sé, esperaba más de un libro así, pero sin embargo ha resultado bastante menos interesante de lo que esperaba. Y no es que esté mal, ni la idea ni el desarrollo, pero sí me ha parecido un tanto flojo.

El libro está compuesto de 33 artículos de otros tantos expertos en el desarrollo que recogen un ejemplo que el significado de código bonito que tiene para ellos mismos. Es decir, cada capítulo explica o está en relación con un ejemplo de código (o una biblioteca, o un sistema completo) y cada autor explica dónde está la belleza del mismo.

Evidentemente cada ensayista tiene un concepto diferente de lo que es código bello. Para unos está en la corrección, para otros en la simplicidad del algoritmo, en otros será la funcionalidad, y así, os lo puedo asegurar, hasta 33 variaciones.

C, C++, PHP, Java, C#, Haskell, Python… prácticamente están presentes todos los lenguajes con algún tipo de presencia actual. También se habla de infinitos temas e infinitas variaciones, desde aplicaciones Web hasta el núcleo de Linux, pasando por bibliotecas matemáticas o C#.

Pero en el libro los lenguajes y los ejemplos están no como demostración per sé, sino como vía para que los autores puedan expresar sus conceptos sobre la belleza del código.

Ciertamente hay ideas interesantes y provocadoras, otras más normales pero siempre interesantes e informativas.

Entre los artículos que me han impresionado está el de Petzold que, mediante el uso de la reflexión en su estado más puro, construye una rutina en MSIL desde código C# y luego la ejecuta para obtener el código más rápido (no voy a entrar en detalles sobre haberla hecho en C++/CLI o en C++ nativo y haber llamado al código mediante interop). En otro, uno de los autores de DDD (un debugger gráfico basado en GDB), genera una serie de compilaciones automatizadas para detectar bugs de incompatibilidad entre herramientas y versiones en lo que él mismo llama delta debugging. Lo llamativo del artículo es que se hace sin depurar una sola línea de código.

Otros capítulos son más prosaico, y algunos resultan hasta aburridos como no seas un experto del tema tratado, como cuando hablan de genética y similares.

¿Por qué uso C++? (y V)

Esta entrada es continuación de esta otra.

Aparte de los compiladores embebidos, cada uno de un fabricante y con sus propias idiosincrasias, mi herramienta principal de desarrollo es una versión Team de Visual Studio con todo instalado (me refiero a los analizadores de código y perfiladores y demás), que uso como IDE para todo aunque luego compile por línea de comandos cuando se trata de sistemas embebidos. A fecha de hoy tengo Visual Studio 2008SP1, que actualizaré en cuanto salga la 2010 final.

Uso el complemento de Whole Tomato Visual Assist, que es algo que uno debería instalar al menos cuando haga algo en C y/o C++, porque no tiene precio. El IntelliSense y el ofrecimiento de código funcionan incluso para los proyectos embebidos si alcanza a ver los ficheros adecuados (y ya me encargo yo de que los vea).

Dado que mi máquina principal es un Quad con 8 GB de RAM ejecutando Windows 7 de 64 bits, muchos (la gran mayoría) de los compiladores y herramientas de terceros para embedded no funcionan directamente bajo este sistema operativo, y más aún cuando hay mochilas y JTAGs de por medio, por lo que suelo tener una buena colección de máquinas virtuales, cada una de ellas conteniendo una tecnología. Uso vmWare porque, pese a lo que tarda a arrancar el programa en sí, es el que más rendimiento me da y con el que soporta más dispositivos montados en virtual. Además, lo tengo configurado de tal modo que cada máquina virtual sabe qué periféricos cargarse al inicio, de modo que no tengo que hacer apenas nada aparte de lanzar el sistema operativo deseado.

También suelo depurar en remoto sobre Windows XP/Vista o 7 cuando la cosa se complica y tendría que enmarranar mi sistema añadiendo drivers y cosas de terceros. Siempre que puedo lo hago con vmWare, pero a veces tengo que usar ordenadores físicos reales, y tengo dos para pruebas y una colección de placas base para montar rápidamente varias configuraciones más o menos estándar.

Muchos compiladores embebidos están en su máquina virtual, así como SDKs de terceros que o bien se pelean entre sí o bien para separar tecnologías y/o fabricantes. Me resulta mucho más claro y rápido localizar la máquina virtual del fabricante A y saber que todo lo que necesito está ahí dentro. Muchas veces, cuando llama algún cliente y sé en qué anda, mientras cojo el teléfono y empiezo a hablar tengo la vm cargada y lista para buscar la respuesta.

Todo mi código fuente está en el ordenador host, y cuando tengo que compilar algo desde una máquina virtual lo que suelo hacer es usar las carpetas compartidas del vmWare, y si eso no funciona porque el compilador es más pejigueras de lo normal, copio el código a la vm, lo compilo y saco el resultado volviendo a copiar, todo ello hecho de forma automática con algún tipo de scrpit.

En su momento intenté disponer de todo esto primero en Virtual PC, luego con discos virtualizados de MS y Windows Server y finalmente con el XP Mode de Windows 7, pero al final ha resultado imposible en primer lugar porque no todos los dispositivos USB conectados en virtual funcionan (eso en XP Mode, porque las otras tecnologías ni siquiera soportan USB), y menos aún aquellos conectados por puertos serie o paralelo, y no es que MS me haya hecho mucho caso pese a estar en la beta del XP Mode. Además, salvo en el último, el rendimiento de la pantalla virtual es más que penoso, sobre todo en los servidores, que encima me dan otros problemas con los JTAG que sí funcionan sin virtualizar en los mismos Windows clientes.

Otras de las herramientas que suelo usar habitualmente son el CursorWorkshop y el IconWorshop de Axialis, Paint.NET, Camtasia y Cygnus Hex Editor, todos ellos cortesía por ser MVP.

Bueno, pues eso es todo. Espero no haber levantado susceptibilidades con lo que he escrito, pero si ha sido así, piénsate a ver por qué te mosquea lo que digo. Y sí, sí que voy a darme el gustazo de comentarios que a) trabajo desde casa con muy pocas salidas y viajes, y b) no tengo horario fijo ni hago casi extras, o más bien sí que lo tengo pero no suelo cumplirlo muy a rajatabla, con el beneplácito de mis jefes (evidentemente se entiende que cumplo absolutamente todos mis objetos no solo a tiempo, sino muchas veces con tiempo de sobra, aunque la mayoría de situaciones son de las de “no importa lo que te cueste ni el tiempo que tardes, simplemente hazlo”). También hay que entender que yo no estoy en una cadena de producción de software (y esa es otra cosa de la que podríamos escribir largo y tendido y echarnos unas risas sobre la mentalidad de muchas empresas).