Odkazování na nativní knihovny v Xamarin. iOSReferencing Native Libraries in Xamarin.iOS

Xamarin. iOS podporuje propojení s nativními knihovnami jazyka C i s cílovými knihovnami jazyka C.Xamarin.iOS supports linking with both native C libraries and Objective-C libraries. Tento dokument popisuje, jak propojit nativní knihovny jazyka C s vaším projektem Xamarin. iOS.This document discusses how to link your native C libraries with your Xamarin.iOS project. Informace o tom, jak to samé provést pro knihovny pro cílení na jazyk C, najdete v našem dokumentu s vytvářením vazeb – typy jazyka c .For information on doing the same for Objective-C libraries, see our Binding Objective-C Types document.

Vytváření univerzálních nativních knihoven (i386, ARMv7 a ARM64)Building Universal Native Libraries (i386, ARMv7, and ARM64)

Často je žádoucí sestavit 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í).It is often desirable to build your native libraries for each of the supported platforms for iOS development (i386 for the Simulator and ARMv7/ARM64 for the devices themselves). Pokud už máte projekt Xcode pro vaši knihovnu, je to ve skutečnosti to jednoduché.If you've already got an Xcode project for your library, this is really trivial to do.

Chcete-li vytvořit verzi i386 vaší nativní knihovny, spusťte následující příkaz z terminálu:To build the i386 version of your native library, run the following command from a terminal:

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

Výsledkem bude nativní Statická knihovna v rámci MyProject.xcodeproj/build/Release-iphonesimulator/ .This will result in a native static library under MyProject.xcodeproj/build/Release-iphonesimulator/. Zkopírujte (nebo přesuňte) soubor archivu knihovny (libMyLibrary. a), aby se někde došlo bezpečný pro pozdější použití, a to tak, aby byl jedinečný název (například libMyLibrary-i386. a), aby nekoliduje s verzemi arm64 a ARMv7 stejné knihovny, které vytvoříte jako další.Copy (or move) the library archive file (libMyLibrary.a) to someplace safe for later use, giving it a unique name (such as libMyLibrary-i386.a) so that it doesn't clash with the arm64 and armv7 versions of the same library that you will build next.

Chcete-li vytvořit verzi ARM64 vaší nativní knihovny, spusťte následující příkaz:To build the ARM64 version of your native library, run the following command:

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

Tentokrát bude sestavena vytvořená nativní knihovna v umístění MyProject.xcodeproj/build/Release-iphoneos/ .This time the built native library will be located in MyProject.xcodeproj/build/Release-iphoneos/. Znovu zkopírujte (nebo přesuňte) Tento soubor do bezpečného umístění, přejmenujte ho na něco jako libMyLibrary-arm64. a tak, aby nedošlo ke konfliktu.Once again, copy (or move) this file to a safe location, renaming it to something like libMyLibrary-arm64.a so that it won't clash.

Nyní Sestavte verzi ARMv7 knihovny:Now build the ARMv7 version of the library:

/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 ostatní 2 verze knihovny, a přejmenujte ji na něco, jako je libMyLibrary-ARMv7. a.Copy (or move) the resulting library file to the same location you moved the other 2 versions of the library, renaming it to something like libMyLibrary-armv7.a.

Chcete-li vytvořit univerzální binární soubor, můžete použít lipo nástroj podobný tomuto:To make a universal binary, you can use the lipo tool like so:

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

Vytvoří se tím libMyLibrary.a Univerzální knihovna (FAT), která bude vhodná pro použití pro všechny cíle vývoje iOS.This creates libMyLibrary.a which will be a universal (fat) library which will be suitable to use for all iOS development targets.

Chybějící požadovaná architektura i386Missing Required Architecture i386

Pokud se vám does not implement methodSignatureForSelector does not implement doesNotRecognizeSelector při pokusu o využití knihovny cílů v programu iOS v simulátoru iOS zobrazuje výstup zprávy nebo, Knihovna pravděpodobně není zkompilována pro architekturu i386 (viz část sestavování univerzálních nativních knihoven výše).If you are getting a does not implement methodSignatureForSelector or does not implement doesNotRecognizeSelector message in your Runtime Output when trying to consume an Objective-C library in the iOS Simulator, your library probably was not compiled for the i386 architecture (see the Building Universal Native Libraries section above).

K ověření architektury podporovaných určitou knihovnou použijte v terminálu následující příkaz:To check the architectures supported by a given library, use the following command in the Terminal:

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

Kde /full/path/to/ je úplná cesta k spotřebované knihovně a libraryname.a je název příslušné knihovny.Where /full/path/to/ is the full path to the library being consumed and libraryname.a is the name of the library in question.

Pokud máte zdroj do knihovny, budete ho muset zkompilovat a vytvořit také pro architekturu i386, pokud chcete otestovat aplikaci v simulátoru iOS.If you have the source to the library, you'll need to compile and bundle it for the i386 architecture as well, if you want to test your app on the iOS simulator.

Propojování knihovnyLinking Your Library

Všechny knihovny třetích stran, které využíváte, musí být staticky propojené s vaší aplikací.Any third-party library that you consume needs to be statically linked with your application.

Pokud jste chtěli staticky propojit knihovnu "libMyLibrary. a", kterou jste získali z Internetu nebo vytvořit pomocí Xcode, budete muset udělat několik věcí:If you wanted to statically link the library "libMyLibrary.a" that you got from the Internet or build with Xcode, you would need to do a few things:

  • Přenesení knihovny do projektuBring the Library into your project
  • Konfigurace Xamarin. iOS pro propojení knihovnyConfigure Xamarin.iOS to link the library
  • Přístup k metodám z knihovny.Access the methods from the library.

Pokud chcete knihovnu přenést do projektu, vyberte projekt v Průzkumníku řešení a stiskněte Command + Option + a.To bring the library into your project, Select the project from the solution explorer and press Command+Option+a. Přejděte na libMyLibrary. a a přidejte ho do projektu.Navigate to the libMyLibrary.a and add it to the project. Po zobrazení výzvy sdělte Visual Studio pro Mac nebo aplikaci Visual Studio, aby se zkopírovala do projektu.When prompted, tell Visual Studio for Mac or Visual Studio to copy it into the project. Po jeho přidání vyhledejte libFoo. a v projektu, klikněte na něj pravým tlačítkem a nastavte akci sestavení na žádná.After adding it, find the libFoo.a in the project, right click on it, and set the Build Action to none.

Chcete-li Konfigurovat Xamarin. iOS, aby provedla propojování knihovny, v možnostech projektu pro finální spustitelný soubor (ne do samotné knihovny, ale konečný program) je nutné přidat do nadbytečného argumentu buildu iOS(tyto jsou součástí možností projektu gcc_flags), za kterým následuje řetězec v uvozovkách, který obsahuje všechny nadbytečné knihovny, které jsou požadovány pro váš program, například:To Configure Xamarin.iOS To Link the Library, on the project options for your final executable (not the library itself, but the final program) you need to add in iOS Build's Extra argument (these are part of your project options) the "-gcc_flags" option followed by a quoted string that contains all the extra libraries that are required for your program, for example:

-gcc_flags "-L${ProjectDir} -lMylibrary -force_load ${ProjectDir}/libMyLibrary.a"

Výše uvedený příklad připojí libMyLibrary. a.The above example will link libMyLibrary.a

Můžete použít -gcc_flags k určení libovolné sady argumentů příkazového řádku, které se mají předat kompilátoru RSZ použitým pro poslední odkaz na spustitelný soubor.You can use -gcc_flags to specify any set of command line arguments to pass to the GCC compiler used to do the final link of your executable. Například Tento příkazový řádek, odkazuje také na CFNetwork Framework:For example, this command line, also references the CFNetwork framework:

-gcc_flags "-L${ProjectDir} -lMylibrary -lSystemLibrary -framework CFNetwork -force_load ${ProjectDir}/libMyLibrary.a"

Pokud vaše nativní knihovna obsahuje kód jazyka C++, musíte také předat příznak-příponu CXX ve vašich "dalších argumentech", aby mohl Xamarin. iOS použít správný kompilátor.If your native library contains C++ code you must also pass the -cxx flag in your "Extra Arguments" so that Xamarin.iOS knows to use the correct compiler. V jazyce C++ by předchozí možnosti vypadaly takto:For C++ the previous options would look like:

-cxx -gcc_flags "-L${ProjectDir} -lMylibrary -lSystemLibrary -framework CFNetwork -force_load ${ProjectDir}/libMyLibrary.a"

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

V systému iOS jsou k dispozici dva druhy nativních knihoven:There are two kinds of native libraries available on iOS:

  • Sdílené knihovny, které jsou součástí operačního systému.Shared libraries that are part of the operating system.

  • Statické knihovny dodávané s vaší aplikací.Static libraries that you ship with your application.

Chcete-li získat přístup k metodám definovaným v jednom z těchto hodnot, použijte funkce nespravovaného volání mono , což je stejná technologie, jakou byste použili v .NET, což je zhruba:To access methods defined in either one of those, you use Mono's P/Invoke functionality which is the same technology that you would use in .NET, which is roughly:

  • Určení funkce jazyka C, kterou chcete vyvolatDetermine which C function you want to invoke
  • Určení jeho signaturyDetermine its signature
  • Určení knihovny, ve které žijeDetermine which library it lives in
  • Zapsat příslušnou deklaraci volání nespravovaného voláníWrite the appropriate P/Invoke declaration

Když použijete P/Invoke, musíte zadat cestu knihovny, se kterou propojujete.When you use P/Invoke you need to specify the path of the library that you are linking with. Pokud používáte sdílené knihovny iOS, můžete cestu buď nekódujte pevně, nebo můžete použít praktické konstanty, které jsme v naší části definovali Constants . Tyto konstanty by měly pokrývat sdílené knihovny pro iOS.When using iOS shared libraries, you can either hardcode the path, or you can use the convenience constants that we have defined in our Constants, these constants should cover the iOS shared libraries.

Například pokud jste chtěli vyvolat metodu UIRectFrameUsingBlendMode z knihovny UIKit společnosti Apple, která má tento podpis v jazyce C:For example, if you wanted to invoke the UIRectFrameUsingBlendMode method from Apple's UIKit library which has this signature in C:

void UIRectFrameUsingBlendMode (CGRect rect, CGBlendMode mode);

Vaše deklarace P/Invoke by vypadala takto:Your P/Invoke declaration would look like this:

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

Konstanty. UIKitLibrary jsou pouze konstantou definované jako "/System/Library/Frameworks/UIKit.framework/UIKit", vstupní bod umožňuje volitelně zadat externí název (UIRectFramUsingBlendMode) při vystavení jiného názvu v jazyce C#, kratší RectFrameUsingBlendMode.The Constants.UIKitLibrary is merely a constant defined as "/System/Library/Frameworks/UIKit.framework/UIKit", the EntryPoint lets us specify optionally the external name (UIRectFramUsingBlendMode) while exposing a different name in C#, the shorter RectFrameUsingBlendMode.

Přístup k Dylibsu v jazyce CAccessing C Dylibs

Pokud je potřeba ve vaší aplikaci Xamarin. iOS využívat DYLIB jazyka C, je nutné před voláním atributu použít trochu speciální instalaci DllImport .If you have the need to consume a C Dylib in your Xamarin.iOS application, there is a bit of extra setup that is required before calling the DllImport attribute.

Například pokud máme Animal.dylib s Animal_Version metodou, kterou budeme volat v naší aplikaci, musíme informovat Xamarin. iOS umístění knihovny, než se ji pokusíte spotřebovat.For example, if we have an Animal.dylib with an Animal_Version method that we will be calling in our application, we need to inform Xamarin.iOS of the location of the library before trying to consume it.

Provedete to tak, že upravíte Main.CS soubor a nastavíte jeho vzhled jako na následující:To do this, edit the Main.CS file and make it look like the following:

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 k DYLIB spotřebovaného.Where /full/path/to/ is the full path to the Dylib being consumed. S tímto kódem můžeme následně připojit k Animal_Version metodě následujícím způsobem:With this code in place, we can then link to the Animal_Version method as follows:

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

Statické knihovnyStatic Libraries

Vzhledem k tomu, že můžete použít pouze statické knihovny v systému iOS, neexistuje žádná externí sdílená knihovna, se kterou by bylo možné propojit, takže parametr Path v atributu DllImport musí použít speciální název __Internal (Všimněte si, že se na začátku názvu podíváme na znaky dvojitého podtržítka), a to na rozdíl od názvu cesty.Since you can only use static libraries on iOS, there is no external shared library to link with, so the path parameter in the DllImport attribute needs to use the special name __Internal (note the double underscore characters at the start of the name) as opposed to the path name.

To vynutí, aby DllImport vyhledal symbol metody, na kterou odkazujete v aktuálním programu, místo aby se pokoušel načíst ze sdílené knihovny.This forces DllImport to look up the symbol of the method that you are referencing in the current program, instead of trying to load it from a shared library.