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)을 나중에 사용할 수 있도록 안전한 위치로 복사(또는 이동)하여 다음에 빌드할 동일한 라이브러리의 arm64 및 armv7 버전과 충돌하지 않도록 고유한 이름(예: libMyLibrary-i386.a)을 제공합니다.

네이티브 라이브러리의 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

이렇게 하면 모든 iOS 개발 대상에 사용하기에 적합한 범용(fat) 라이브러리가 만들어 libMyLibrary.a 집니다.

필수 아키텍처 i386 누락

iOS 시뮬레이터에서 라이브러리를 사용 Objective-C 하려고 할 때 런타임 출력에 메시지 또는 does not implement doesNotRecognizeSelector 메시지가 표시되는 경우 does not implement methodSignatureForSelector 라이브러리가 i386 아키텍처용으로 컴파일되지 않았을 수 있습니다(위의 유니버설 네이티브 라이브러리 빌드 섹션 참조).

지정된 라이브러리에서 지원하는 아키텍처를 검사 터미널에서 다음 명령을 사용합니다.

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

사용 중인 라이브러리의 전체 경로는 어디에 /full/path/to/ 있으며 libraryname.a 해당 라이브러리의 이름입니다.

라이브러리에 대한 원본이 있는 경우 iOS 시뮬레이터에서 앱을 테스트하려는 경우 i386 아키텍처용으로 컴파일하고 번들로 묶어야 합니다.

라이브러리 연결

사용하는 모든 타사 라이브러리는 애플리케이션과 정적으로 연결되어야 합니다.

인터넷에서 얻은 라이브러리 "libMyLibrary.a"를 정적으로 연결하거나 Xcode를 사용하여 빌드하려는 경우 몇 가지 작업을 수행해야 합니다.

  • 라이브러리를 프로젝트로 가져오기
  • 라이브러리를 연결하도록 Xamarin.iOS 구성
  • 라이브러리에서 메서드에 액세스합니다.

라이브러리를 프로젝트로 가져오려면 솔루션 탐색기에서 프로젝트를 선택하고 Command+Option+a를 누릅니다. libMyLibrary.a로 이동하여 프로젝트에 추가합니다. 메시지가 표시되면 Mac용 Visual Studio 또는 Visual Studio에 프로젝트에 복사하도록 지시합니다. 추가한 후 프로젝트에서 libFoo.a를 찾아 마우스 오른쪽 단추로 클릭하고 빌드 작업을 없음으로 설정합니다.

라이브러리를 연결하도록 Xamarin.iOS를 구성하려면 iOS 빌드의 추가 인수(프로젝트 옵션의 일부)에 추가해야 하는 최종 실행 파일의 프로젝트 옵션에 "-gcc_flags" 옵션과 프로그램에 필요한 모든 추가 라이브러리가 포함된 따옴표 붙은 문자열을 추가해야 합니다. 예를 들어:

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

위의 예제에서는 libMyLibrary.a를 연결 합니다.

실행 파일의 최종 링크를 수행하는 데 사용되는 GCC 컴파일러에 전달할 명령줄 인수 집합을 지정하는 데 사용할 -gcc_flags 수 있습니다. 예를 들어 이 명령줄은 CFNetwork 프레임워크도 참조합니다.

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

네이티브 라이브러리에 C++ 코드가 포함된 경우 Xamarin.iOS에서 올바른 컴파일러를 사용할 수 있도록 "추가 인수"에 -cxx 플래그도 전달해야 합니다. C++의 경우 이전 옵션은 다음과 같습니다.

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

C에서 C 메서드 액세스#

iOS에서 사용할 수 있는 네이티브 라이브러리에는 두 가지 종류가 있습니다.

  • 운영 체제의 일부인 공유 라이브러리입니다.

  • 애플리케이션과 함께 제공되는 정적 라이브러리입니다.

이러한 방법 중 하나에 정의된 메서드에 액세스하려면 .NET에서 사용하는 것과 동일한 기술인 Mono의 P/Invoke 기능을 사용합니다. 이는 대략 다음과 같습니다.

  • 호출할 C 함수 결정
  • 서명 확인
  • 해당 라이브러리가 있는 라이브러리 확인
  • 적절한 P/Invoke 선언 작성

P/Invoke를 사용하는 경우 연결할 라이브러리의 경로를 지정해야 합니다. iOS 공유 라이브러리를 사용하는 경우 경로를 하드 코딩하거나 정의한 편리한 상수 Constants를 사용할 수 있습니다. 이러한 상수는 iOS 공유 라이브러리를 포함해야 합니다.

예를 들어 이 서명이 C인 Apple의 UIKit 라이브러리에서 UIRectFrameUsingBlendMode 메서드를 호출하려는 경우:

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를 사용하면 C#에서 다른 이름인 짧은 RectFrameUsingBlendMode를 노출하면서 선택적으로 외부 이름(UIRectFramUsingBlendMode)을 지정할 수 있습니다.

C Dylibs 액세스

Xamarin.iOS 애플리케이션에서 C Dylib를 사용해야 하는 경우 특성을 호출 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");
}

Dylib가 사용되는 전체 경로는 어디에 /full/path/to/ 있나요? 이 코드를 사용하면 다음과 같이 메서드에 Animal_Version 연결할 수 있습니다.

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

정적 라이브러리

iOS에서만 정적 라이브러리를 사용할 수 있으므로 연결할 외부 공유 라이브러리가 없으므로 DllImport 특성의 경로 매개 변수는 경로 이름이 아닌 특수 이름 __Internal (이름 시작 부분에 이중 밑줄 문자 참고)을 사용해야 합니다.

따라서 DllImport는 공유 라이브러리에서 로드하는 대신 현재 프로그램에서 참조하는 메서드의 기호를 조회합니다.