Los universos de C++
El entorno Windows
1. Los programas Win32
La plataforma Win32 fue rápidamente soportada por C++, porque Microsoft lanzó en 1992 uno de los primeros entornos integrados para este lenguaje; era Visual C++, y en ese momento, muchos arquitectos estaban convencidos del interés de un lenguaje de objetos cercano al lenguaje C para crear aplicaciones que se ejecutaran en entornos gráficos.
Sin embargo, programar una aplicación con ventana, sin un framework, no es una tarea fácil. El hecho es que la plataforma Win32 ofrece varios formatos de aplicación: aplicaciones de "consola", servicios de Windows, librerías dinámicas (DLL) y, por supuesto, aplicaciones de gráficos en ventanas.
No existe un modelo de proyecto "Win64" porque Windows sigue siendo un sistema muy arraigado en el modo de 32 bits. Sin embargo, Visual Studio sabe compilar en modo de 64 bits desde un proyecto Win32.
2. Elección del modo de compilación
La creación de un proyecto se realiza con el comando Archivo - Nuevo Proyecto:
Desde el Administrador de configuraciones, el modo de compilación 64 bits está activado:
El siguiente programa es interesante; indica que el tamaño de los tipos int y long es el mismo en un modo de 32 bits.
printf("Programa compilado en modo 64 bits\n");
printf("tamaño int %d\n", sizeof(int));
printf("tamaño long %d\n", sizeof(long));
El modo de 64 bits recomienda que el compilador genere instrucciones de microprocesador de 64 bits, pero eso no significa que los tipos se ajusten en consecuencia. En otras palabras, un cálculo en un tipo __int64 podría tardar más tiempo en 32 bits que en 64, pero __int64 siempre existe en 64 bits e int existe en 4 bytes para cualquier modo de compilación. Esta es una característica especial del compilador de Microsoft; otros compiladores pueden comportarse de manera diferente.
3. Funcionamiento de las aplicaciones de ventana Win32
No hay diferencia estructural entre el ejecutable de la consola y el de escritorio. Estas son llamadas al sistema que activan el cambio al modo de ventana.
Sin embargo, el funcionamiento de una aplicación de ventana es bastante particular, ya que el programa debe reaccionar a las entradas del usuario (clic del ratón, accesos directos de teclado...
El entorno .NET
1. Le código gestionado y la máquina virtual CLR
Igual que sucede con Java, .NET es parte de la familia de entornos virtualizados. El compilador C++ administrado no genera código ensamblador que se pueda ejecutar directamente por el microprocesador, sino un código intermedio, ejecutado a su vez por una máquina "virtual", el CLR (Common Language Runtime). Esta capa de software reproduce todos los componentes de un ordenador: memoria, procesador, entradas-salidas, etc.
Esta máquina se debe adaptar al sistema operativo que la aloja y, sobre todo, optimizar la ejecución del código.
Aquí hay una diferencia importante entre .NET y Java. Si bien Microsoft obviamente ha optado por centrarse en la plataforma Windows, otros editores han adaptado Java a sus respectivos sistemas operativos: Unix, AIX, Mac OS o Linux. Sin embargo, la empresa Novell ha logrado adoptar .Net en Linux, dentro del proyecto Mono.
Este entorno virtualizado tiene una consecuencia muy importante sobre los lenguajes soportados; los tipos de datos y los mecanismos del objeto son los de la CLR. Como Microsoft estaba en un proceso de unificación de sus entornos, se consideraron elegibles para la CLR varios lenguajes, incluso si eso significaba adaptar un poco su definición. El proyecto de Sun fue más una creación desde cero y, por lo tanto, solo se promovió realmente el lenguaje Java en la máquina virtual JVM.
2. Las adaptaciones del lenguaje C++ CLI
El término CLI significa Common Language Infrastructure. Es el conjunto de adaptaciones necesarias para el funcionamiento de C++ para la plataforma .NET/CLR.
a. La norma CTS
El primer cambio se refiere a los tipos de datos. Como sucesor de C, el C++ estándar basaba su tipología en la palabra máquina (int) y el carácter de 8 bits (char). Frente a problemas de estandarización e interoperabilidad, Microsoft optó por unificar los tipos de datos entre sus diferentes lenguajes.
Los tipos primitivos, destinados a ser utilizados como variables locales (bucles, algoritmos, etc.), son tipos por "valor". Su área de almacenamiento natural es la pila (stack), y su definición pertenece a el espacio de nombres System:
wchar_t |
System::Char |
Caracter unicode |
signed char |
System::SByte |
Byte firmado |
unsigned char |
System::Byte |
Byte no firmado |
double |
System::Double... |
Trabajos prácticos
1. Realizar una aplicación de dibujo Win32
Usamos el formato de aplicación Win32 estudiado al principio del capítulo, para crear un programa capaz de mostrar dos tipos de dibujos generados por cálculo C++.
Nuestro proyecto se llama “C++ Win UI”.
El primer paso es agregar nuevas entradas Ver - Área y Ver - Fractal al menú de la aplicación. Para hacer esto, debe abrir el archivo de recursos y editar el menú IDC_CWINUI:
El carácter subrayado se utiliza como atajo de teclado (también decimos acelerador). Se obtiene anteponiendo a la letra A (luego, respectivamente, S y F) un signo &.
Para designar cada tipo de dibujo, definimos una enumeración en el archivo C++ WinUI.cpp:
enum Mostrar { Area, Fractal } visualización;
La función wWinMain() reemplaza a la función tradicional main(). Esta es una posible ubicación para inicializar la variable visualización:
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: sitúe el código aquí.
visualización = Mostrar::Area;
La función WndProc() trata los mensajes de la aplicación. Cada entrada del menú se corresponde con una acción de WM_COMMAND:
LRESULT CALLBACK WndProc(HWND hWnd, UINT mensaje, WPARAM wParam, LPARAM lParam)
{
switch (mensaje)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Análiza...