Référencement de bibliothèques natives dans Xamarin.iOS

Xamarin.iOS prend en charge la liaison avec les bibliothèques et Objective-C bibliothèques C natives. Ce document explique comment lier vos bibliothèques C natives à votre projet Xamarin.iOS. Pour plus d’informations sur le fait d’en faire de même pour Objective-C les bibliothèques, consultez notre document Types de liaisonsObjective-C.

Génération de bibliothèques natives universelles (i386, ARMv7 et ARM64)

Il est souvent souhaitable de créer vos bibliothèques natives pour chacune des plateformes prises en charge pour le développement iOS (i386 pour le simulateur et ARMv7/ARM64 pour les appareils eux-mêmes). Si vous avez déjà un projet Xcode pour votre bibliothèque, cela est vraiment trivial.

Pour générer la version i386 de votre bibliothèque native, exécutez la commande suivante à partir d’un terminal :

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

Cela entraîne une bibliothèque statique native sous MyProject.xcodeproj/build/Release-iphonesimulator/. Copiez (ou déplacez) le fichier d’archive de bibliothèque (libMyLibrary.a) vers un emplacement sûr pour une utilisation ultérieure, en lui attribuant un nom unique (par exemple libMyLibrary-i386.a) afin qu’il n’entre pas en conflit avec les versions arm64 et armv7 de la même bibliothèque que vous allez générer ensuite.

Pour générer la version ARM64 de votre bibliothèque native, exécutez la commande suivante :

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

Cette fois, la bibliothèque native générée se trouve dans MyProject.xcodeproj/build/Release-iphoneos/. Une fois de plus, copiez (ou déplacez) ce fichier vers un emplacement sécurisé, en le renommant comme libMyLibrary-arm64.a afin qu’il ne soit pas en conflit.

Générez maintenant la version ARMv7 de la bibliothèque :

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

Copiez (ou déplacez) le fichier de bibliothèque résultant à l’emplacement où vous avez déplacé les 2 autres versions de la bibliothèque, en le renommant libMyLibrary-armv7.a.

Pour créer un binaire universel, vous pouvez utiliser l’outil lipo comme suit :

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

Cela crée libMyLibrary.a qui sera une bibliothèque universelle (fat) qui sera adaptée à l’utilisation pour toutes les cibles de développement iOS.

Architecture requise manquante i386

Si vous recevez un does not implement methodSignatureForSelector message ou does not implement doesNotRecognizeSelector dans votre sortie d’exécution lorsque vous essayez de consommer une Objective-C bibliothèque dans le simulateur iOS, votre bibliothèque n’a probablement pas été compilée pour l’architecture i386 (voir la section Création de bibliothèques natives universelles ci-dessus).

Pour case activée les architectures prises en charge par une bibliothèque donnée, utilisez la commande suivante dans le terminal :

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

/full/path/to/ est le chemin d’accès complet à la bibliothèque consommée et libraryname.a est le nom de la bibliothèque en question.

Si vous avez la source de la bibliothèque, vous devez également la compiler et la regrouper pour l’architecture i386, si vous souhaitez tester votre application sur le simulateur iOS.

Liaison de votre bibliothèque

Toute bibliothèque tierce que vous consommez doit être liée de manière statique à votre application.

Si vous souhaitez lier statiquement la bibliothèque « libMyLibrary.a » que vous avez obtenue à partir d’Internet ou créer avec Xcode, vous devez effectuer quelques opérations :

  • Intégrer la bibliothèque dans votre projet
  • Configurer Xamarin.iOS pour lier la bibliothèque
  • Accédez aux méthodes à partir de la bibliothèque.

Pour intégrer la bibliothèque dans votre projet, sélectionnez le projet dans l’Explorateur de solutions, puis appuyez sur Cmd+Option+a. Accédez à libMyLibrary.a et ajoutez-le au projet. Lorsque vous y êtes invité, indiquez Visual Studio pour Mac ou Visual Studio de le copier dans le projet. Après l’avoir ajouté, recherchez libFoo.a dans le projet, cliquez dessus avec le bouton droit et définissez l’action de génération sur none.

Pour configurer Xamarin.iOS Pour lier la bibliothèque, dans les options de projet de votre fichier exécutable final (pas la bibliothèque elle-même, mais le programme final), vous devez ajouter dans l’argument Extra de la build iOS (celles-ci font partie des options de votre projet) l’option « -gcc_flags » suivie d’une chaîne entre guillemets qui contient toutes les bibliothèques supplémentaires requises pour votre programme, par exemple :

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

L’exemple ci-dessus lie libMyLibrary.a

Vous pouvez utiliser -gcc_flags pour spécifier n’importe quel ensemble d’arguments de ligne de commande à passer au compilateur GCC utilisé pour effectuer le lien final de votre exécutable. Par exemple, cette ligne de commande fait également référence à l’infrastructure CFNetwork :

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

Si votre bibliothèque native contient du code C++, vous devez également passer l’indicateur -cxx dans vos arguments supplémentaires afin que Xamarin.iOS sache utiliser le compilateur approprié. Pour C++, les options précédentes ressemblent à ceci :

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

Accès aux méthodes C à partir de C#

Il existe deux types de bibliothèques natives disponibles sur iOS :

  • Bibliothèques partagées qui font partie du système d’exploitation.

  • Bibliothèques statiques que vous livrez avec votre application.

Pour accéder aux méthodes définies dans l’une de ces méthodes, vous utilisez la fonctionnalité P/Invoke de Mono , qui est la même technologie que celle que vous utiliseriez dans .NET, à savoir approximativement :

  • Déterminer la fonction C que vous souhaitez appeler
  • Déterminer sa signature
  • Déterminer la bibliothèque dans laquelle il se trouve
  • Écrire la déclaration P/Invoke appropriée

Lorsque vous utilisez P/Invoke, vous devez spécifier le chemin de la bibliothèque avec laquelle vous êtes lié. Lorsque vous utilisez des bibliothèques partagées iOS, vous pouvez soit coder en dur le chemin d’accès, soit utiliser les constantes pratiques que nous avons définies dans notre Constants, ces constantes doivent couvrir les bibliothèques partagées iOS.

Par exemple, si vous souhaitez appeler la méthode UIRectFrameUsingBlendMode à partir de la bibliothèque UIKit d’Apple qui a cette signature en C :

void UIRectFrameUsingBlendMode (CGRect rect, CGBlendMode mode);

Votre déclaration P/Invoke se présente comme suit :

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

Constants.UIKitLibrary est simplement une constante définie comme « /System/Library/Frameworks/UIKit.framework/UIKit ». EntryPoint nous permet de spécifier éventuellement le nom externe (UIRectFramUsingBlendMode) tout en exposant un autre nom en C#, rectFrameUsingBlendMode plus court.

Accès à C Dylibs

Si vous avez besoin de consommer un Dylib C dans votre application Xamarin.iOS, une configuration supplémentaire est requise avant d’appeler l’attribut DllImport .

Par exemple, si nous avons un Animal.dylib avec une Animal_Version méthode que nous allons appeler dans notre application, nous devons informer Xamarin.iOS de l’emplacement de la bibliothèque avant d’essayer de l’utiliser.

Pour ce faire, modifiez le Main.CS fichier et faites-le ressembler à ce qui suit :

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

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

/full/path/to/ est le chemin d’accès complet au Dylib consommé. Une fois ce code en place, nous pouvons ensuite établir un lien vers la Animal_Version méthode comme suit :

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

Bibliothèques statiques

Étant donné que vous ne pouvez utiliser des bibliothèques statiques que sur iOS, il n’existe aucune bibliothèque partagée externe à lier. Par conséquent, le paramètre path dans l’attribut DllImport doit utiliser le nom __Internal spécial (notez les caractères de soulignement doubles au début du nom) par opposition au nom du chemin d’accès.

Cela force DllImport à rechercher le symbole de la méthode que vous référencez dans le programme actuel, au lieu d’essayer de le charger à partir d’une bibliothèque partagée.