Condividi tramite


Riferimento a librerie native in Xamarin.iOS

Xamarin.iOS supporta il collegamento con librerie e Objective-C librerie C native. Questo documento illustra come collegare le librerie C native al progetto Xamarin.iOS. Per informazioni su come eseguire la stessa operazione per Objective-C le raccolte, vedere il documento Tipi di associazioneObjective-C.

Compilazione di librerie native universali (i386, ARMv7 e ARM64)

Spesso è consigliabile creare librerie native per ognuna delle piattaforme supportate per lo sviluppo iOS (i386 per il simulatore e ARMv7/ARM64 per i dispositivi stessi). Se è già disponibile un progetto Xcode per la libreria, questa operazione è davvero semplice.

Per compilare la versione i386 della libreria nativa, eseguire il comando seguente da un terminale:

/Developer/usr/bin/xcodebuild -project MyProject.xcodeproj -target MyLibrary -sdk iphonesimulator -arch i386 -configuration Release clean build

Ciò comporterà una libreria statica nativa in MyProject.xcodeproj/build/Release-iphonesimulator/. Copiare (o spostare) il file di archivio della libreria (libMyLibrary.a) in un luogo sicuro per usarlo in un secondo momento, assegnando un nome univoco (ad esempio libMyLibrary-i386.a) in modo che non si scontri con le versioni arm64 e armv7 della stessa libreria che verrà compilata successivamente.

Per compilare la versione ARM64 della libreria nativa, eseguire il comando seguente:

/Developer/usr/bin/xcodebuild -project MyProject.xcodeproj -target MyLibrary -sdk iphoneos -arch arm64 -configuration Release clean build

Questa volta la libreria nativa compilata si troverà in MyProject.xcodeproj/build/Release-iphoneos/. Ancora una volta, copiare (o spostare) questo file in un percorso sicuro, rinominarlo in un modo simile a libMyLibrary-arm64.a in modo che non si scontri.

Compilare ora la versione ARMv7 della libreria:

/Developer/usr/bin/xcodebuild -project MyProject.xcodeproj -target MyLibrary -sdk iphoneos -arch armv7 -configuration Release clean build

Copiare (o spostare) il file di libreria risultante nella stessa posizione in cui sono state spostate le altre 2 versioni della libreria, rinominandolo in un modo simile a libMyLibrary-armv7.a.

Per creare un file binario universale, è possibile usare lo lipo strumento come segue:

lipo -create -output libMyLibrary.a libMyLibrary-i386.a libMyLibrary-arm64.a libMyLibrary-armv7.a

Verrà creata libMyLibrary.a una libreria universale (fat) che sarà adatta per l'uso per tutte le destinazioni di sviluppo iOS.

Architettura richiesta mancante i386

Se si riceve un does not implement methodSignatureForSelector messaggio o does not implement doesNotRecognizeSelector nell'output di runtime quando si tenta di usare una Objective-C libreria nel simulatore iOS, la libreria probabilmente non è stata compilata per l'architettura i386 (vedere la sezione Compilazione di librerie native universali sopra).

Per controllare le architetture supportate da una determinata libreria, usare il comando seguente nel terminale:

lipo -info /full/path/to/libraryname.a

Dove /full/path/to/ è il percorso completo della libreria utilizzata ed libraryname.a è il nome della libreria in questione.

Se si dispone dell'origine per la libreria, sarà necessario compilarlo e aggregarlo anche per l'architettura i386, se si vuole testare l'app nel simulatore iOS.

Collegamento della libreria

Qualsiasi libreria di terze parti utilizzata deve essere collegata in modo statico all'applicazione.

Se si vuole collegare in modo statico la libreria "libMyLibrary.a" ottenuta da Internet o compilare con Xcode, è necessario eseguire alcune operazioni:

  • Inserire la libreria nel progetto
  • Configurare Xamarin.iOS per collegare la libreria
  • Accedere ai metodi dalla libreria.

Per inserire la libreria nel progetto, selezionare il progetto da Esplora soluzioni e premere Comando+Opzione+a. Passare a libMyLibrary.a e aggiungerlo al progetto. Quando richiesto, indicare a Visual Studio per Mac o Visual Studio di copiarlo nel progetto. Dopo averlo aggiunto, trovare libFoo.a nel progetto, fare clic con il pulsante destro del mouse su di esso e impostare l'azione di compilazione su nessuno.

Per configurare Xamarin.iOS per collegare la libreria, nelle opzioni di progetto per il file eseguibile finale (non la libreria stessa, ma il programma finale) è necessario aggiungere l'argomento Extra di compilazione iOS (queste fanno parte delle opzioni del progetto) l'opzione "-gcc_flags" seguita da una stringa tra virgolette che contiene tutte le librerie aggiuntive necessarie per il programma, Per esempio:

-gcc_flags "-L$(MSBuildProjectDirectory) -lMylibrary -force_load $(MSBuildProjectDirectory)/libMyLibrary.a"

L'esempio precedente collega libMyLibrary.a

È possibile usare -gcc_flags per specificare qualsiasi set di argomenti della riga di comando da passare al compilatore GCC usato per eseguire il collegamento finale del file eseguibile. Ad esempio, questa riga di comando fa riferimento anche al framework CFNetwork:

-gcc_flags "-L$(MSBuildProjectDirectory) -lMylibrary -lSystemLibrary -framework CFNetwork -force_load $(MSBuildProjectDirectory)/libMyLibrary.a"

Se la libreria nativa contiene codice C++, è necessario passare anche il flag -cxx in "Argomenti aggiuntivi" in modo che Xamarin.iOS sappia usare il compilatore corretto. Per C++ le opzioni precedenti sono simili alle seguenti:

-cxx -gcc_flags "-L$(MSBuildProjectDirectory) -lMylibrary -lSystemLibrary -framework CFNetwork -force_load $(MSBuildProjectDirectory)/libMyLibrary.a"

Accesso ai metodi C da C#

In iOS sono disponibili due tipi di librerie native:

  • Librerie condivise che fanno parte del sistema operativo.

  • Librerie statiche fornite con l'applicazione.

Per accedere ai metodi definiti in uno di questi, è possibile usare la funzionalità P/Invoke di Mono, che è la stessa tecnologia usata in .NET, che è approssimativamente:

  • Determinare quale funzione C si desidera richiamare
  • Determinare la firma
  • Determinare la libreria in cui risiede
  • Scrivere la dichiarazione P/Invoke appropriata

Quando si usa P/Invoke, è necessario specificare il percorso della libreria con cui si esegue il collegamento. Quando si usano librerie condivise iOS, è possibile impostare come hardcoded il percorso oppure usare le costanti di praticità definite in Constants, queste costanti devono coprire le librerie condivise iOS.

Ad esempio, se si vuole richiamare il metodo UIRectFrameUsingBlendMode dalla libreria UIKit di Apple con questa firma in C:

void UIRectFrameUsingBlendMode (CGRect rect, CGBlendMode mode);

La dichiarazione P/Invoke sarà simile alla seguente:

[DllImport (Constants.UIKitLibrary,EntryPoint="UIRectFrameUsingBlendMode")]
public extern static void RectFrameUsingBlendMode (RectangleF rect, CGBlendMode blendMode);

Constants.UIKitLibrary è semplicemente una costante definita come "/System/Library/Frameworks/UIKit.framework/UIKit", EntryPoint consente di specificare facoltativamente il nome esterno (UIRectFramUsingBlendMode) esponendo un nome diverso in C#, rectFrameUsingBlendMode più breve.

Accesso a C Dylibs

Se è necessario usare un C Dylib nell'applicazione Xamarin.iOS, è necessaria una configurazione aggiuntiva prima di chiamare l'attributo DllImport .

Ad esempio, se si dispone di un Animal.dylib oggetto con un Animal_Version metodo che verrà chiamato nell'applicazione, è necessario informare Xamarin.iOS del percorso della libreria prima di provare a usarlo.

A tale scopo, modificare il Main.CS file e renderlo simile al seguente:

static void Main (string[] args)
{
    // Load Dylib
    MonoTouch.ObjCRuntime.Dlfcn.dlopen ("/full/path/to/Animal.dylib", 0);

    // Start application
    UIApplication.Main (args, null, "AppDelegate");
}

Dove /full/path/to/ è il percorso completo del Dylib utilizzato. Con questo codice sul posto, è quindi possibile collegarsi al Animal_Version metodo come indicato di seguito:

[DllImport("Animal.dylib", EntryPoint="Animal_Version")]
public static extern double AnimalLibraryVersion();

Librerie statiche

Poiché è possibile usare solo librerie statiche in iOS, non esiste una libreria condivisa esterna con cui collegarsi, pertanto il parametro path nell'attributo DllImport deve usare il nome __Internal speciale (si notino i caratteri di sottolineatura doppia all'inizio del nome) anziché il nome del percorso.

In questo modo DllImport cerca il simbolo del metodo a cui si fa riferimento nel programma corrente, anziché tentare di caricarlo da una libreria condivisa.