Ссылка на собственные библиотеки в Xamarin.iOS

Xamarin.iOS поддерживает связывание как с собственными библиотеками C, так и Objective-C с библиотеками. В этом документе описывается связывание собственных библиотек C с проектом Xamarin.iOS. Сведения о том, как это сделать для Objective-C библиотек, см. в документе "Типы привязкиObjective-C".

Создание универсальных собственных библиотек (i386, ARMv7 и ARM64)

Часто рекомендуется создавать собственные библиотеки для каждой из поддерживаемых платформ для разработки iOS (i386 для симулятора и ARMv7/ARM64 для самих устройств). Если у вас уже есть проект Xcode для вашей библиотеки, это действительно тривиальное действие.

Чтобы создать версию i386 собственной библиотеки, выполните следующую команду из терминала:

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

Это приведет к тому, что в собственной статической библиотеке будет вложена MyProject.xcodeproj/build/Release-iphonesimulator/. Скопируйте (или переместите) архивный файл библиотеки (libMyLibrary.a) в безопасное место для последующего использования, предоставляя ему уникальное имя (например , libMyLibrary-i386.a), чтобы оно не сталкивалось с версиями arm64 и armv7 той же библиотеки, которую вы создадите далее.

Чтобы создать версию ARM64 собственной библиотеки, выполните следующую команду:

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

На этот раз встроенная библиотека будет находиться в MyProject.xcodeproj/build/Release-iphoneos/. Еще раз скопируйте (или переместите) этот файл в безопасное расположение, переименуя его на что-то вроде libMyLibrary-arm64.a , чтобы оно не столкнулось.

Теперь создайте версию ARMv7 библиотеки:

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

Скопируйте (или переместите) полученный файл библиотеки в то же место, где вы переместили другие 2 версии библиотеки, переименуя его на что-то подобное libMyLibrary-armv7.a.

Чтобы сделать универсальный двоичный файл, можно использовать lipo средство, как показано ниже.

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

Это создает libMyLibrary.a универсальную библиотеку (fat), которая будет подходить для всех целевых целей разработки iOS.

Отсутствует требуемая архитектура i386

Если вы получаете does not implement methodSignatureForSelector или does not implement doesNotRecognizeSelector сообщение в выходных данных среды выполнения при попытке использовать Objective-C библиотеку в симуляторе iOS, ваша библиотека, вероятно, не была скомпилирована для архитектуры i386 (см . раздел "Сборка универсальных собственных библиотек" выше).

Чтобы проверка архитектуры, поддерживаемые данной библиотекой, используйте следующую команду в терминале:

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

Где /full/path/to/ находится полный путь к используемой библиотеке и libraryname.a имя библиотеки, в которой находится вопрос.

Если у вас есть источник библиотеки, необходимо скомпилировать и упаковать его для архитектуры i386, если вы хотите протестировать приложение на симуляторе iOS.

Связывание библиотеки

Любая сторонняя библиотека, которую вы используете, должна быть статически связана с приложением.

Если вы хотите статически связать библиотеку libMyLibrary.a, полученную из Интернета или сборку с помощью Xcode, вам потребуется выполнить несколько действий:

  • Перенос библиотеки в проект
  • Настройка Xamarin.iOS для связывания библиотеки
  • Доступ к методам из библиотеки.

Чтобы перенести библиотеку в проект, выберите проект из обозревателя решений и нажмите клавиши Command+Option+a. Перейдите к libMyLibrary.a и добавьте его в проект. При появлении запроса сообщите Visual Studio для Mac или Visual Studio, чтобы скопировать его в проект. Добавив его, найдите libFoo.a в проекте, щелкните его правой кнопкой мыши и задайте для действиясборки значение none.

Чтобы настроить ссылку на библиотеку Xamarin.iOS, в параметрах проекта для окончательного исполняемого файла (а не самой библиотеки, а последней программы) необходимо добавить в дополнительный аргумент сборки iOS (это часть параметров проекта) параметр "-gcc_flags", а затем в кавычки строку, содержащую все дополнительные библиотеки, необходимые для вашей программы, Например:

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

Приведенный выше пример будет ссылаться на libMyLibrary.a

Можно использовать -gcc_flags для указания любого набора аргументов командной строки для передачи в компилятор GCC, используемый для выполнения конечной ссылки исполняемого файла. Например, эта командная строка также ссылается на платформу CFNetwork:

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

Если в собственной библиотеке содержится код C++, необходимо также передать флаг -cxx в поле "Дополнительные аргументы", чтобы Xamarin.iOS знал, что использует правильный компилятор. Для C++ предыдущие параметры будут выглядеть следующим образом:

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

Доступ к методам C из C#

Существует два типа собственных библиотек, доступных в iOS:

  • Общие библиотеки, которые являются частью операционной системы.

  • Статические библиотеки, которые вы отправляете с приложением.

Для доступа к методам, определенным в одном из них, используется функция Mono P/Invoke, которая является той же технологией, которую вы будете использовать в .NET, что примерно так:

  • Определение функции C, которую требуется вызвать
  • Определение подписи
  • Определение библиотеки, в которой она находится
  • Написание соответствующего объявления P/Invoke

При использовании P/Invoke необходимо указать путь к библиотеке, с которым вы связываетесь. При использовании общих библиотек iOS можно закодировать путь или использовать удобные константы, определенные в нашей среде Constants, эти константы должны охватывать общие библиотеки iOS.

Например, если вы хотите вызвать метод UIRectFrameUsingBlendMode из библиотеки UIKit Apple, которая имеет эту подпись в C:

void UIRectFrameUsingBlendMode (CGRect rect, CGBlendMode mode);

Объявление P/Invoke будет выглядеть следующим образом:

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

Constants.UIKitLibrary является просто константой, определенной как "/System/Library/Frameworks/UIKit.framework/UIKit", в EntryPoint можно указать дополнительно внешнее имя (UIRectFramUsingBlendMode), предоставляя другое имя в C#, короче RectFrameUsingBlendMode.

Доступ к Dylibs

Если у вас есть необходимость использовать Dylib в приложении Xamarin.iOS, перед вызовом DllImport атрибута требуется дополнительная настройка.

Например, если у нас есть Animal.dylibAnimal_Version метод, который мы будем вызывать в нашем приложении, необходимо сообщить Xamarin.iOS о расположении библиотеки, прежде чем пытаться использовать его.

Для этого измените Main.CS файл и сделайте его следующим образом:

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/ находится полный путь к используемому Dylib. В этом коде мы можем связаться с методом Animal_Version следующим образом:

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

Статические библиотеки

Так как вы можете использовать только статические библиотеки в iOS, нет внешней общей библиотеки для связи, поэтому параметр пути в атрибуте DllImport должен использовать специальное имя __Internal (запишите двойные символы подчеркивания в начале имени) в отличие от имени пути.

Это заставляет DllImport искать символ метода, который вы ссылаетесь в текущей программе, а не пытаться загрузить его из общей библиотеки.