Verweisen auf native Bibliotheken in Xamarin.iOS

Xamarin.iOS unterstützt das Verknüpfen sowohl mit nativen C-Bibliotheken Objective-C als auch mit Bibliotheken. In diesem Dokument wird erläutert, wie Sie Ihre nativen C-Bibliotheken mit Ihrem Xamarin.iOS-Projekt verknüpfen. Informationen dazu, wie Sie dies auch für Objective-C Bibliotheken tun, finden Sie in unserem Dokument bindungstypenObjective-C.

Erstellen von universellen nativen Bibliotheken (i386, ARMv7 und ARM64)

Es ist häufig wünschenswert, Ihre nativen Bibliotheken für jede der unterstützten Plattformen für die iOS-Entwicklung zu erstellen (i386 für den Simulator und ARMv7/ARM64 für die Geräte selbst). Wenn Sie bereits über ein Xcode-Projekt für Ihre Bibliothek verfügen, ist dies wirklich trivial.

Um die i386-Version Ihrer nativen Bibliothek zu erstellen, führen Sie den folgenden Befehl über ein Terminal aus:

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

Dies führt zu einer nativen statischen Bibliothek unter MyProject.xcodeproj/build/Release-iphonesimulator/. Kopieren (oder verschieben) Sie die Bibliotheksarchivdatei (libMyLibrary.a) an einen sicheren Ort für die spätere Verwendung, und geben Sie ihr einen eindeutigen Namen (z. B. libMyLibrary-i386.a), damit sie nicht mit den arm64- und armv7-Versionen derselben Bibliothek kollidiert, die Sie als Nächstes erstellen werden.

Führen Sie den folgenden Befehl aus, um die ARM64-Version Ihrer nativen Bibliothek zu erstellen:

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

Dieses Mal befindet sich die erstellte native Bibliothek in MyProject.xcodeproj/build/Release-iphoneos/. Kopieren (oder verschieben) Sie diese Datei erneut an einen sicheren Speicherort, und umbenennen Sie sie in etwa libMyLibrary-arm64.a , damit sie nicht kollidiert.

Erstellen Sie nun die ARMv7-Version der Bibliothek:

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

Kopieren (oder verschieben) Sie die resultierende Bibliotheksdatei an den gleichen Speicherort, an dem Sie die anderen 2 Versionen der Bibliothek verschoben haben, und umbenennen Sie sie in etwa libMyLibrary-armv7.a.

Um eine universelle Binärdatei zu erstellen, können Sie das lipo Tool wie folgt verwenden:

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

Dadurch wird eine universelle (fette) Bibliothek erstellt libMyLibrary.a , die für alle iOS-Entwicklungsziele geeignet ist.

Fehlende erforderliche Architektur i386

Wenn Sie beim Versuch, eine Objective-C Bibliothek im iOS-Simulator zu nutzen, eine oder does not implement doesNotRecognizeSelector eine does not implement methodSignatureForSelector Meldung in der Laufzeitausgabe erhalten, wurde Ihre Bibliothek wahrscheinlich nicht für die i386-Architektur kompiliert (siehe Abschnitt Erstellen universeller nativer Bibliotheken oben).

Verwenden Sie den folgenden Befehl im Terminal, um die von einer bestimmten Bibliothek unterstützten Architekturen zu überprüfen:

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

Dabei /full/path/to/ ist der vollständige Pfad zur verwendeten Bibliothek und libraryname.a der Name der betreffenden Bibliothek.

Wenn Sie über die Quelle für die Bibliothek verfügen, müssen Sie sie auch für die i386-Architektur kompilieren und bündeln, wenn Sie Ihre App im iOS-Simulator testen möchten.

Verknüpfen ihrer Bibliothek

Jede drittanbieterbasierte Bibliothek, die Sie nutzen, muss statisch mit Ihrer Anwendung verknüpft werden.

Wenn Sie die Bibliothek "libMyLibrary.a", die Sie aus dem Internet erhalten haben, statisch verknüpfen oder mit Xcode erstellen möchten, müssen Sie einige Schritte ausführen:

  • Integrieren der Bibliothek in Ihr Projekt
  • Konfigurieren von Xamarin.iOS zum Verknüpfen der Bibliothek
  • Greifen Sie über die Bibliothek auf die Methoden zu.

Um die Bibliothek in Ihr Projekt zu integrieren, wählen Sie das Projekt im Projektmappen-Explorer aus, und drücken Sie BEFEHL+WAHL+a. Navigieren Sie zu libMyLibrary.a, und fügen Sie sie dem Projekt hinzu. Wenn Sie dazu aufgefordert werden, weisen Sie Visual Studio für Mac oder Visual Studio an, sie in das Projekt zu kopieren. Suchen Sie nach dem Hinzufügen der Datei libFoo.a im Projekt, klicken Sie mit der rechten Maustaste darauf, und legen Sie die Buildaktion auf keine fest.

Um Xamarin.iOS zum Verknüpfen der Bibliothek zu konfigurieren, müssen Sie in den Projektoptionen für Ihre endgültige ausführbare Datei (nicht die Bibliothek selbst, sondern das endgültige Programm) im Argument Extra von iOS Build (dies sind Teil Ihrer Projektoptionen) die Option "-gcc_flags" gefolgt von einer Zeichenfolge in Anführungszeichen hinzufügen, die alle zusätzlichen Bibliotheken enthält, die für Ihr Programm erforderlich sind, Zum Beispiel:

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

Im obigen Beispiel wird libMyLibrary.a verknüpft.

Sie können verwenden -gcc_flags , um einen beliebigen Satz von Befehlszeilenargumenten anzugeben, der an den GCC-Compiler übergeben werden soll, der zum Erstellen des endgültigen Links Ihrer ausführbaren Datei verwendet wird. Diese Befehlszeile verweist beispielsweise auch auf das CFNetwork-Framework:

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

Wenn Ihre native Bibliothek C++-Code enthält, müssen Sie auch das Flag -cxx in Ihren "Zusätzlichen Argumenten" übergeben, damit Xamarin.iOS den richtigen Compiler verwendet. Für C++ würden die vorherigen Optionen wie folgt aussehen:

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

Zugreifen auf C-Methoden von C aus#

Unter iOS stehen zwei Arten von nativen Bibliotheken zur Verfügung:

  • Freigegebene Bibliotheken, die Teil des Betriebssystems sind.

  • Statische Bibliotheken, die Sie mit Ihrer Anwendung bereitstellen.

Für den Zugriff auf methoden, die in einer dieser Methoden definiert sind, verwenden Sie die P/Invoke-Funktionalität von Mono . Dies ist die gleiche Technologie, die Sie in .NET verwenden würden. Dies ist ungefähr:

  • Bestimmen, welche C-Funktion Sie aufrufen möchten
  • Bestimmen der Signatur
  • Bestimmen, in welcher Bibliothek es sich befindet
  • Schreiben der entsprechenden P/Invoke-Deklaration

Wenn Sie P/Invoke verwenden, müssen Sie den Pfad der Bibliothek angeben, mit der Sie eine Verknüpfung herstellen. Wenn Sie freigegebene iOS-Bibliotheken verwenden, können Sie entweder den Pfad hartcodieren, oder Sie können die Komfortkonstanten verwenden, die wir in unserem Constantsdefiniert haben. Diese Konstanten sollten die freigegebenen iOS-Bibliotheken abdecken.

Wenn Sie beispielsweise die UIRectFrameUsingBlendMode-Methode aus der UIKit-Bibliothek von Apple aufrufen möchten, die diese Signatur in C aufweist:

void UIRectFrameUsingBlendMode (CGRect rect, CGBlendMode mode);

Ihre P/Invoke-Deklaration sieht wie folgt aus:

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

Constants.UIKitLibrary ist lediglich eine Konstante, die als "/System/Library/Frameworks/UIKit.framework/UIKit" definiert ist. EntryPoint ermöglicht es uns, optional den externen Namen (UIRectFramUsingBlendMode) anzugeben, während ein anderer Name in C# verfügbar gemacht wird, dem kürzeren RectFrameUsingBlendMode.

Zugreifen auf C Dylibs

Wenn Sie eine C Dylib in Ihrer Xamarin.iOS-Anwendung verwenden müssen, ist vor dem Aufrufen des DllImport Attributs ein bisschen zusätzliche Einrichtung erforderlich.

Wenn wir beispielsweise eine Animal.dylib mit einer Animal_Version Methode haben, die wir in unserer Anwendung aufrufen, müssen wir Xamarin.iOS über den Speicherort der Bibliothek informieren, bevor wir versuchen, sie zu nutzen.

Bearbeiten Sie dazu die Main.CS Datei, und lassen Sie sie wie folgt aussehen:

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

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

Dabei /full/path/to/ ist der vollständige Pfad zum verwendeten Dylib. Wenn dieser Code vorhanden ist, können wir dann wie folgt mit der Animal_Version -Methode verknüpfen:

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

Statische Bibliotheken

Da Sie nur statische Bibliotheken unter iOS verwenden können, gibt es keine externe freigegebene Bibliothek, mit der eine Verknüpfung hergestellt werden kann. Daher muss der path-Parameter im DllImport-Attribut den speziellen Namen __Internal (beachten Sie die doppelten Unterstriche am Anfang des Namens) anstelle des Pfadnamens verwenden.

Dadurch wird erzwungen, dass DllImport das Symbol der Methode sucht, auf die Sie im aktuellen Programm verweisen, anstatt es aus einer freigegebenen Bibliothek zu laden.