Enlaces de Xamarin.Mac en aplicaciones de consola

Hay algunos escenarios en los que le conviene usar las API nativas de Apple en C# para compilar una aplicación sin IU mediante C#.

Las plantillas de proyecto para aplicaciones Mac incluyen una llamada a NSApplication.Init() seguida de una llamada a NSApplication.Main(args), normalmente tiene el siguiente aspecto:

static class MainClass {
    static void Main (string [] args)
    {
        NSApplication.Init ();
        NSApplication.Main (args);
    }
}

La llamada a Init prepara el runtime de Xamarin.Mac, la llamada a Main(args) inicia el bucle principal de la aplicación Cocoa, que prepara la aplicación para recibir eventos de teclado y mouse, y mostrar la ventana principal de la aplicación. La llamada a Main también intentará asignar recursos de Cocoa, preparar una ventana de nivel superior y esperar a que el programa forme parte de una agrupación de aplicaciones (programas distribuidos en un directorio con la extensión .app y un diseño muy específico).

Las aplicaciones sin interfaz de usuario no necesitan ejecutarse como parte de una agrupación de aplicaciones.

Creación de la aplicación de consola

Por lo tanto, es mejor empezar con un tipo de proyecto de consola de .NET normal.

Debe hacer algunas cosas:

  • Creación de un proyecto vacío.
  • Hacer referencia a la biblioteca de Xamarin.Mac.dll.
  • Incorporar la dependencia no administrada al proyecto.

Estos pasos se explican con más detalle a continuación:

Cree un proyecto de consola vacío

Cree un nuevo proyecto de consola de .NET, asegúrese de que es .NET y no .NET Core, ya que Xamarin.Mac.dll no se ejecuta en el entorno de ejecución de .NET Core, solo se ejecuta con el entorno de ejecución de Mono.

Haga referencia a la biblioteca de Xamarin.Mac

Para compilar el código, querrá hacer referencia al Xamarin.Mac.dll ensamblado desde este directorio: /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/64bits/full

Para ello, vaya a las referencias del proyecto, seleccione la pestaña Ensamblado de .NET y haga clic en el botón Examinar para buscar el archivo en el sistema de archivos. Vaya a la ruta de acceso anterior y, a continuación, seleccione Xamarin.Mac.dll de ese directorio.

Esto le proporcionará acceso a las API de Cocoa en tiempo de compilación. En este momento, puede agregar using AppKit al principio del archivo y llamar al método NSApplication.Init(). Solo hay un paso más para poder ejecutar la aplicación.

Incorporación de la biblioteca de apoyo no administrada al proyecto

Antes de que se ejecute la aplicación, debe incluir la biblioteca de apoyo en el proyecto Xamarin.Mac. Para ello, agregue un nuevo archivo al proyecto (en las opciones del proyecto, seleccione Agregar y, después, Agregar archivo existente) y vaya a este directorio:

/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/SDKs/Xamarin.macOS.sdk/lib

Aquí, seleccione el archivo libxammac.dylib. Se le ofrecerá una opción de copia, vinculación o movimiento. Personalmente me gusta vincular, pero copiar también funciona. A continuación, seleccione el archivo y vaya al panel de propiedades (si no ve el panel de propiedades, seleccione Ver>Paneles>Propiedades), vaya a la sección Compilación y establezca la opción Copiar en directorio de salida en Copiar si es más reciente.

Ahora puede ejecutar la aplicación Xamarin.Mac.

El resultado en el directorio bin será así:

Xamarin.Mac.dll
Xamarin.Mac.pdb
consoleapp.exe
consoleapp.pdb
libxammac.dylib

Para ejecutar esta aplicación, necesitará todos esos archivos en el mismo directorio.

Crear una aplicación independiente para la distribución

Puede que quiera distribuir un único archivo ejecutable a los usuarios. Para ello, puede usar la herramienta mkbundle para convertir los distintos archivos en un ejecutable autocontenido.

En primer lugar, asegúrese de que la aplicación se compila y se ejecuta. Cuando los resultados le satisfagan, puede ejecutar el siguiente comando desde la línea de comandos:

$ mkbundle --simple -o /tmp/consoleapp consoleapp.exe --library libxammac.dylib --config /Library/Frameworks/Mono.framework/Versions/Current/etc/mono/config --machine-config /Library/Frameworks/Mono.framework/Versions/Current/etc/mono/4.5/machine.config
[Output from the bundling tool]
$ _

En la invocación de la línea de comandos anterior, la opción -o se usa para especificar la salida generada, en este caso, hemos pasado /tmp/consoleapp. Ahora es una aplicación independiente que puede distribuir y no tiene dependencias externas en Mono o Xamarin.Mac, es un ejecutable totalmente independiente.

La línea de comandos especificó manualmente el archivo machine.config que se va a usar y un archivo de configuración de asignación de biblioteca en todo el sistema. No son necesarios para todas las aplicaciones, pero es conveniente agruparlos, ya que se usan cuando use más funcionalidades de .NET

Compilaciones sin proyecto

No necesita un proyecto completo para crear una aplicación de Xamarin.Mac independiente. También puede usar archivos make de Unix simples para realizar el trabajo. En el ejemplo siguiente se muestra cómo puede configurar un archivo make para una aplicación de línea de comandos sencilla:

XAMMAC_PATH=/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/x86_64/full/
DYLD=/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib
MONODIR=/Library/Frameworks/Mono.framework/Versions/Current/etc/mono

all: consoleapp.exe

consoelapp.exe: consoleapp.cs Makefile
    mcs -g -r:$(XAMMAC_PATH)/Xamarin.Mac.dll consoleapp.cs
    
run: consoleapp.exe
    MONO_PATH=$(XAMMAC_PATH) DYLD_LIBRARY_PATH=$(DYLD) mono --debug consoleapp.exe $(COMMAND)

bundle: consoleapp.exe
    mkbundle --simple consoleapp.exe -o ncsharp -L $(XAMMAC_PATH) --library $(DYLD)/libxammac.dylib --config $(MONODIR)/config --machine-config $(MONODIR)/4.5/machine.config

El Makefile anterior proporciona tres destinos:

  • make compilará el programa
  • make run compilará y ejecutará el programa en el directorio actual
  • make bundle creará un ejecutable autocontenido