Xamarin.Mac 아키텍처

이 가이드에서는 Xamarin.Mac과 해당 관계를 Objective-C 낮은 수준에서 살펴봅니다. 컴파일, 선택기, 앱 시작 및 생성기와 registrars같은 개념을 설명합니다.

개요

Xamarin.Mac 애플리케이션은 Mono 실행 환경 내에서 실행되며 Xamarin의 컴파일러를 사용하여 IL(Intermediate Language)로 컴파일한 다음, 런타임에 네이티브 코드로 컴파일된 JIT(Just-In-Time)입니다. 런타임과 Objective-C 나란히 실행됩니다. 두 런타임 환경은 모두 UNIX와 유사한 커널( 특히 XNU)에서 실행되며 개발자가 기본 네이티브 또는 관리되는 시스템에 액세스할 수 있도록 사용자 코드에 다양한 API를 노출합니다.

아래 다이어그램은 이 아키텍처의 기본 개요를 보여줍니다.

Diagram showing a basic overview of the architecture

네이티브 및 관리 코드

Xamarin용으로 개발할 때 네이티브관리 코드라는 용어가 자주 사용됩니다. 관리 코드는 .NET Framework 공용 언어 런타임 또는 Xamarin의 경우 Mono 런타임에서 실행되는 코드입니다.

네이티브 코드는 특정 플랫폼(예 Objective-C : ARM 칩의 AOT 컴파일 코드)에서 기본적으로 실행되는 코드입니다. 이 가이드에서는 관리 코드가 네이티브 코드로 컴파일되는 방법을 살펴보고 Xamarin.Mac 애플리케이션이 작동하는 방식을 설명하며, 바인딩을 사용하여 Apple의 Mac API를 최대한 활용하면서 액세스 권한을 갖습니다. NET의 BCL 및 C#과 같은 정교한 언어.

요구 사항

Xamarin.Mac으로 macOS 애플리케이션을 개발하려면 다음이 필요합니다.

  • macOS Sierra(10.12) 이상을 실행하는 Mac입니다.
  • 최신 버전의 Xcode(App Store에서 설치됨)
  • 최신 버전의 Xamarin.Mac 및 Mac용 Visual Studio

Xamarin.Mac으로 만든 Mac 애플리케이션을 실행하려면 다음과 같은 시스템 요구 사항이 필요합니다.

  • Mac OS X 10.7 이상을 실행하는 Mac.

컴파일

Xamarin 플랫폼 애플리케이션을 컴파일하면 Mono C#(또는 F#) 컴파일러가 실행되고 C# 및 F# 코드를 MSIL 또는 IL(Microsoft Intermediate Language)으로 컴파일합니다. 그런 다음 Xamarin.Mac은 런타임에 JIT(Just in Time) 컴파일러를 사용하여 네이티브 코드를 컴파일하여 필요에 따라 올바른 아키텍처에서 실행을 허용합니다.

이는 AOT 컴파일을 사용하는 Xamarin.iOS와는 대조적입니다. AOT 컴파일러를 사용하는 경우 모든 어셈블리와 해당 어셈블리 내의 모든 메서드는 빌드 시 컴파일됩니다. JIT를 사용하면 컴파일은 실행되는 메서드에 대해서만 요청 시 발생합니다.

Xamarin.Mac 애플리케이션을 사용하는 경우 Mono는 일반적으로 앱 번들에 포함됩니다(포함된 Mono라고 함). 클래식 Xamarin.Mac API를 사용하는 경우 애플리케이션에서 System Mono를 대신 사용할 수 있지만 통합 API에서는 지원되지 않습니다. System Mono는 운영 체제에 설치된 Mono를 나타냅니다. 애플리케이션을 시작할 때 Xamarin.Mac 앱에서 이를 사용합니다.

선택기

Xamarin을 사용하면 최종 목표가 원활한 사용자 환경이 되도록 가능한 한 간소화된 것처럼 보이도록 함께 모아야 하는 .NET과 Apple이라는 두 개의 별도 에코시스템이 있습니다. 위의 섹션에서 두 런타임이 통신하는 방법을 확인했으며, 네이티브 Mac API를 Xamarin에서 사용할 수 있는 '바인딩'이라는 용어에 대해 잘 들어보셨을 것입니다. 바인딩은 바인딩 설명서Objective-C 자세히 설명되어 있으므로 지금은 Xamarin.Mac이 내부적으로 작동하는 방식을 살펴보겠습니다.

먼저 선택기를 통해 수행되는 C#에 노출 Objective-C 하는 방법이 있어야 합니다. 선택기는 개체 또는 클래스로 전송되는 메시지입니다. Objective-C 이 작업은 objc_msgSend 함수를 통해 수행됩니다. 선택기 사용에 대한 자세한 내용은 iOS Objective-C 선택기 가이드를 참조하세요. 관리 코드에 대해 아무것도 모르기 때문에 관리 코드를 노출하는 Objective-CObjective-C 방법도 있어야 합니다. 이를 해결하려면 .를 registrar사용합니다. 이 내용은 다음 섹션에서 자세히 설명합니다.

Registrar

위에서 registrar 멘션 관리 코드를 노출하는 코드Objective-C입니다. NSObject에서 파생되는 모든 관리되는 클래스 목록을 만들어 이 작업을 수행합니다.

  • 기존 Objective-C 클래스를 래핑하지 않는 모든 클래스의 경우 특성이 있는 모든 관리되는 멤버를 미러 멤버를 사용하여 새 Objective-C 클래스 Objective-C 를 [Export] 만듭니다.
  • 각 Objective–C 멤버에 대한 구현에서 코드가 자동으로 추가되어 미러 관리되는 멤버를 호출합니다.

아래 의사 코드는 이 작업을 수행하는 방법의 예를 보여 줍니다.

C#(관리 코드):

class MyViewController : UIViewController{
    [Export ("myFunc")]
    public void MyFunc ()
    {
    }
 }

Objective-C (네이티브 코드):

@interface MyViewController : UIViewController
 - (void)myFunc;
@end

@implementation MyViewController
- (void)myFunc {
    // Code to call the managed C# MyFunc method in MyViewController
}
@end

관리 코드는 특성을 포함할 수 있으며[Export], [Register] 개체를 registrar 노출Objective-C해야 한다는 것을 알기 위해 사용합니다. [Register] 특성은 생성된 기본 이름이 적합하지 않은 경우 생성된 Objective-C 클래스의 이름을 지정하는 데 사용됩니다. NSObject에서 파생된 모든 클래스는 자동으로 .에 Objective-C등록됩니다. 필수 [Export] 특성에는 생성된 클래스에서 사용되는 선택기인 문자열이 포함됩니다 Objective-C .

Xamarin.Mac에는 동적 및 정적의 두 가지 유형 registrars 이 사용됩니다.

  • 동적 registrars – 모든 Xamarin.Mac 빌드의 기본값 registrar 입니다. 동적 registrar 은 런타임에 어셈블리의 모든 형식을 등록합니다. 이 작업은 '런타임 API에서 제공하는 Objective-C함수를 사용하여 수행합니다. 따라서 동적 registrar 은 시작 속도가 느리지만 빌드 시간이 빨라집니다. 트램폴린이라고 하는 네이티브 함수(일반적으로 C)는 동적 registrars함수를 사용할 때 메서드 구현으로 사용됩니다. 아키텍처는 서로 다릅니다.
  • 정적 registrars – 정적 registrar 은 빌드 중에 코드를 생성 Objective-C 한 다음, 정적 라이브러리로 컴파일되고 실행 파일에 연결됩니다. 이렇게 하면 더 빠르게 시작할 수 있지만 빌드 시간 동안 더 오래 걸립니다.

애플리케이션 시작

Xamarin.Mac 시작 논리는 임베디드 또는 시스템 Mono 사용 여부에 따라 달라집니다. Xamarin.Mac 애플리케이션 시작에 대한 코드 및 단계를 보려면 xamarin-macios 공용 리포지토리의 시작 헤더 파일을 참조하세요.

생성기

Xamarin.Mac에는 모든 Mac API에 대한 정의가 포함되어 있습니다. MaciOS github 리포지토리에서 이러한 리포지토리를 탐색할 수 있습니다. 이러한 정의에는 특성이 있는 인터페이스와 필요한 메서드 및 속성이 포함됩니다. 예를 들어 다음 코드는 AppKit 네임스페이스에서 NSBox를 정의하는 데 사용됩니다. 다음과 같은 여러 메서드와 속성이 있는 인터페이스입니다.

[BaseType (typeof (NSView))]
public interface NSBox {

    …

    [Export ("borderRect")]
    CGRect BorderRect { get; }

    [Export ("titleRect")]
    CGRect TitleRect { get; }

    [Export ("titleCell")]
    NSObject TitleCell { get; }

    [Export ("sizeToFit")]
    void SizeToFit ();

    [Export ("contentViewMargins")]
    CGSize ContentViewMargins { get; set; }

    [Export ("setFrameFromContentFrame:")]
    void SetFrameFromContentFrame (CGRect contentFrame);

    …

}

Xamarin.Mac에서 호출 bmac 된 생성기는 이러한 정의 파일을 사용하고 .NET 도구를 사용하여 임시 어셈블리로 컴파일합니다. 그러나 이 임시 어셈블리는 코드를 호출 Objective-C 하는 데 사용할 수 없습니다. 그런 다음 생성기는 임시 어셈블리를 읽고 런타임에 사용할 수 있는 C# 코드를 생성합니다. 따라서 예를 들어 정의 .cs 파일에 임의 특성을 추가하면 출력된 코드에 표시되지 않습니다. 생성기는 이에 대해 알지 못하므로 bmac 생성기를 출력하기 위해 임시 어셈블리에서 찾을 수 없습니다.

Xamarin.Mac.dll 만들어지면 패키지 사용자는 mmp모든 구성 요소를 함께 번들로 묶습니다.

높은 수준에서 다음 작업을 실행하여 이를 달성합니다.

  • 앱 번들 구조를 만듭니다.
  • 관리되는 어셈블리에 복사합니다.
  • 연결을 사용하는 경우 관리되는 링커를 실행하여 사용되지 않는 부분을 제거하여 어셈블리를 최적화합니다.
  • 시작 관리자 애플리케이션을 만들고, 정적 모드인 경우 코드와 함께 registrar 설명된 시작 관리자 코드에 연결합니다.

그런 다음 사용자 코드를 참조하는 어셈블리로 컴파일하고 Xamarin.Mac.dll 패키지로 만드는 사용자 빌드 프로세스의 일부로 실행됩니다 mmp .

링커 및 링커 사용 방법에 대한 자세한 내용은 iOS 링커 가이드를 참조하세요.

요약

이 가이드에서는 Xamarin.Mac 앱의 컴파일을 살펴보고 Xamarin.Mac과 Xamarin.Mac의 관계를 Objective-C살펴보았습니다.