Odkazování na nativní knihovny v Xamarin.iOS

Xamarin.iOS podporuje propojení s nativními knihovnami jazyka C i Objective-C knihovnami. Tento dokument popisuje, jak propojit nativní knihovny C s projektem Xamarin.iOS. Informace o stejných činnostech pro Objective-C knihovny najdete v dokumentu Typy vazebObjective-C.

Vytváření univerzálních nativních knihoven (i386, ARMv7 a ARM64)

Často je žádoucí vytvářet nativní knihovny pro každou z podporovaných platforem pro vývoj pro iOS (i386 pro simulátor a ARMv7/ARM64 pro samotná zařízení). Pokud už máte projekt Xcode pro vaši knihovnu, je to opravdu triviální.

Pokud chcete sestavit verzi nativní knihovny i386, spusťte z terminálu následující příkaz:

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

Výsledkem bude nativní statická knihovna v části MyProject.xcodeproj/build/Release-iphonesimulator/. Zkopírujte (nebo přesuňte) soubor archivu knihovny (libMyLibrary.a) na některé místo, kde je bezpečné pro pozdější použití, a zadejte jedinečný název (například libMyLibrary-i386.a), aby nepřekážel s verzemi arm64 a armv7 stejné knihovny, kterou vytvoříte dále.

Pokud chcete sestavit verzi ARM64 nativní knihovny, spusťte následující příkaz:

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

Tentokrát bude sestavená nativní knihovna umístěna ve složce MyProject.xcodeproj/build/Release-iphoneos/. Znovu zkopírujte (nebo přesuňte) tento soubor do bezpečného umístění a přejmenujte ho na něco jako libMyLibrary-arm64.a tak, aby se nepřerušil.

Teď sestavte verzi knihovny ARMv7:

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

Zkopírujte (nebo přesuňte) výsledný soubor knihovny do stejného umístění, kam jste přesunuli další 2 verze knihovny, a přejmenujte ho na něco jako libMyLibrary-armv7.a.

Pokud chcete vytvořit univerzální binární soubor, můžete tento nástroj použít lipo takto:

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

Tím se vytvoří libMyLibrary.a univerzální knihovna (fat), která bude vhodná pro použití pro všechny cíle vývoje pro iOS.

Chybí požadovaná architektura i386

Pokud se při pokusu o využití Objective-C knihovny v simulátoru iOS zobrazuje does not implement methodSignatureForSelector zpráva nebo does not implement doesNotRecognizeSelector zpráva ve výstupu modulu runtime, knihovna pravděpodobně nebyla zkompilována pro architekturu i386 (viz část Sestavení univerzálních nativních knihoven výše).

Pokud chcete zkontrolovat architektury podporované danou knihovnou, použijte v terminálu následující příkaz:

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

Kde /full/path/to/ je úplná cesta ke spotřebované knihovně a libraryname.a je název příslušné knihovny.

Pokud máte zdroj knihovny, budete ji muset zkompilovat a sbalit také pro architekturu i386, pokud chcete aplikaci otestovat na simulátoru iOS.

Propojení knihovny

Všechny knihovny třetích stran, které používáte, musí být staticky propojeny s vaší aplikací.

Pokud byste chtěli staticky propojit knihovnu libMyLibrary.a, kterou jste získali z internetu nebo sestavení pomocí Xcode, musíte udělat několik věcí:

  • Přenesení knihovny do projektu
  • Konfigurace Xamarin.iOS pro propojení knihovny
  • Přístup k metodám z knihovny

Pokud chcete přenést knihovnu do projektu, vyberte projekt z Průzkumníka řešení a stiskněte Command+Option+a. Přejděte na knihovnu libMyLibrary.a a přidejte ji do projektu. Po zobrazení výzvy řekněte Visual Studio pro Mac nebo sadě Visual Studio, aby ho zkopírovali do projektu. Po jeho přidání vyhledejte v projektu knihovnu libFoo.a, klikněte na ni pravým tlačítkem myši a nastavte akci sestavení na žádnou.

Pokud chcete nakonfigurovat Xamarin.iOS pro propojení knihovny, v možnostech projektu pro konečný spustitelný soubor (ne samotnou knihovnu, ale konečný program) musíte přidat do argumentu Extra sestavení iOS (jsou součástí možností projektu) možnost -gcc_flags, za kterým následuje řetězec s uvozovkou obsahující všechny knihovny, které jsou pro váš program potřeba, Například:

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

Výše uvedený příklad bude propojit libMyLibrary.a

Můžete použít -gcc_flags k zadání libovolné sady argumentů příkazového řádku, které se předávají kompilátoru GCC použitému k provedení konečného propojení spustitelného souboru. Například tento příkazový řádek odkazuje také na architekturu CFNetwork:

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

Pokud vaše nativní knihovna obsahuje kód C++, musíte také předat příznak -cxx ve vašem extra argumentu, aby Xamarin.iOS věděl, že používá správný kompilátor. U jazyka C++ by předchozí možnosti vypadaly takto:

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

Přístup k metodám jazyka C z jazyka C#

V iOSu jsou k dispozici dva druhy nativních knihoven:

  • Sdílené knihovny, které jsou součástí operačního systému.

  • Statické knihovny, které dodáváte s aplikací.

Pro přístup k metodám definovaným v některé z těchto metod použijete funkci P/Invoke mono, což je stejná technologie, jakou byste použili v .NET, což je zhruba:

  • Určení funkce jazyka C, kterou chcete vyvolat
  • Určení podpisu
  • Určení knihovny, ve které se nachází
  • Napište příslušnou deklaraci volání nespravovaného kódu.

Když použijete volání nespravovaného kódu, musíte zadat cestu ke knihovně, se kterou vytváříte propojení. Při použití sdílených knihoven iOSu můžete cestu pevně zakódovat, nebo můžete použít pohodlné konstanty, které jsme definovali v našich Constants, tyto konstanty by měly zahrnovat sdílené knihovny iOS.

Pokud například chcete vyvolat metodu UIRectFrameUsingBlendMode z knihovny UIKit společnosti Apple, která má tento podpis v jazyce C:

void UIRectFrameUsingBlendMode (CGRect rect, CGBlendMode mode);

Deklarace volání nespravovaného kódu by vypadala takto:

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

Constants.UIKitLibrary je pouze konstanta definovaná jako "/System/Library/Frameworks/UIKit.framework/UIKit", entryPoint nám umožňuje zadat volitelně externí název (UIRectFramUsingBlendMode) při zveřejnění jiného názvu v jazyce C#, kratší rectFrameUsingBlendMode.

Přístup k C Dylibs

Pokud potřebujete použít C Dylib v aplikaci Xamarin.iOS, je před voláním atributu DllImport potřeba trochu dalšího nastavení.

Pokud máme například metodu Animal.dylibAnimal_Version , kterou budeme volat v aplikaci, musíme před pokusem o jeho využití informovat Xamarin.iOS o umístění knihovny.

Uděláte to tak, že Main.CS upravíte soubor a nastavíte ho takto:

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

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

Kde /full/path/to/ je úplná cesta ke spotřebovanému Dylibu. S tímto kódem pak můžeme metodu Animal_Version propojit následujícím způsobem:

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

Statické knihovny

Vzhledem k tomu, že v iOSu můžete používat pouze statické knihovny, neexistuje žádná externí sdílená knihovna, se kterou by bylo možné vytvořit propojení, takže parametr cesty v atributu DllImport musí používat speciální název __Internal (všimněte si dvoutržítka znaků na začátku názvu) místo názvu cesty.

Tím se vynutí, aby dllImport vyhledat symbol metody, na kterou odkazujete v aktuálním programu, místo aby se pokusil načíst ze sdílené knihovny.