다음을 통해 공유


내보낸 멤버 변환

업데이트: 2007년 11월

이 항목에서는 내보내기 프로세스에서 다음 멤버를 변환하는 방법을 설명합니다.

  • 메서드

  • 속성

  • 이벤트

메서드

COM 클라이언트는 메서드를 호출해야 합니다. 이때 매개 변수와 같은 친숙한 COM 데이터 형식을 전달하고 이에 대한 반환 값으로 HRESULT를 받습니다. 그러나 .NET Framework에서 사용하는 클래스는 반환 형식에 대해 이러한 제한이 없으며 사실 HRESULT를 사용하지도 않습니다.

두 모델을 모두 만족시키기 위해 관리되는 형식의 모든 메서드는 .NET 시그니처 및 내포된 COM 시그니처를 가지고 있습니다. 두 시그니처는 일반적으로 아주 다릅니다. .NET 클라이언트는 .NET 시그니처를 사용하여 서버와 상호 작용하는 반면 거의 동시에 COM 클라이언트는 COM 시그니처를 사용하여 서버와 상호 작용합니다. 서버는 .NET 시그니처를 사용하여 메서드를 구현하고 런타임 마샬링 서비스는 관리되는 메서드에 대한 호출을 위임하는 COM 시그니처를 스텁에 제공해야 합니다.

HRESULT 변환

관리되는 반환 값을 [out, retval] 매개 변수로 변경하고 관리되지 않는 반환 값의 형식을 HRESULT로 변경하여 관리되는 시그니처를 관리되지 않는 시그니처로 변환합니다. 예를 들어 DoSomething 메서드는 다음과 같은 시그니처를 가질 수 있습니다.

관리되는 시그니처

short DoSomething(short i);

관리되지 않는 시그니처

HRESULT DoSomething([in] short i, [out, retval] short *rv);

COM 시그니처는 HRESULT를 반환하고 반환 값에 대해 추가 out 매개 변수를 가집니다. 관리되는 구현의 반환 값은 항상 관리되지 않는 시그니처 끝에 추가된 [out, retval] 매개 변수로 반환되는 반면 관리되지 않는 시그니처는 항상 HRESULT를 반환합니다. 관리되는 메서드에 void 반환 형식이 있는 경우 런타임은 [out, retval] 매개 변수를 생략합니다. 예를 들면 다음과 같습니다.

관리되는 시그니처

void DoSomething(short i);

관리되지 않는 시그니처

HRESULT DoSomething([in] short i);

어떤 경우에는 관리되는 시그니처를 변경하지 않는 것이 더 좋습니다. PreserveSigAttribute를 사용하여 이렇게 할 수 있습니다. 예를 들면 다음과 같습니다.

관리되는 시그니처

[PreserveSig] short DoSomething(short i);

관리되지 않는 시그니처

short DoSomething ([in] short i);

고유한 두 메서드 시그니처를 포함하면 COM 클라이언트와 .NET 클라이언트의 클래스를 아무런 문제 없이 손쉽게 사용할 수 있습니다. 또한 COM 클라이언트와 .NET 클라이언트 모두 .NET 클래스를 동시에 사용할 수 있습니다. 클래스 작성자는 관리되는 시그니처만 구현합니다. Tlbexp.exe 또는 이와 동등한 API를 사용하면 클래스에 대해 생성되는 형식 라이브러리로 시그니처를 자동으로 내보낼 수 있습니다.

오버로드된 메서드

.NET은 오버로드된 메서드를 지원하지만 IDispatch 인터페이스는 바인딩할 때 전체 메서드 시그니처 대신 메서드 이름에만 전적으로 의존합니다. 따라서 오버로드된 메서드를 지원할 수 없습니다. 그러나 형식의 오버로드된 메서드에 액세스할 수 있도록 하기 위해 Tlbexp.exe는 오버로드된 메서드의 이름을 서수로 데코레이션하여 각 메서드 이름을 고유하게 만듭니다.

아래의 관리되는 시그니처와 관리되지 않는 시그니처는 이러한 서수 포함을 보여 줍니다.

관리되는 시그니처

interface INew {
public:
    void DoSomething();
    void DoSomething(short s);
    void DoSomething(short l);
    void DoSomething(float f);
    void DoSomething(double d);
}

관리되지 않는 시그니처

interface INew {
    void DoSomething();
    void DoSomething_2(short s);
    void DoSomething_3(short l);
    void DoSomething_4(float f);
    void DoSomething_5(double d);
}

메서드의 COM 시그니처는 단일 DoSomething 메서드 뒤에 데코레이션된 일련의 DoSomething_x 메서드로 나타납니다. 여기서 x는 2부터 시작하고 메서드의 각 오버로드된 형식에 대해 값이 증가합니다. 일부 오버로드된 메서드는 기본 형식에서 상속될 수 있습니다. 그러나 오버로드된 메서드가 형식 버전이 증가할 때 항상 동일한 값을 유지하는 것은 아닙니다.

.NET 클라이언트가 메서드의 오버로드된 형식을 사용할 수 있더라도 COM 클라이언트는 데코레이션된 메서드에 액세스해야 합니다. 개체 브라우저는 메서드 시그니처와 함께 모든 형식의 데코레이션된 메서드를 표시하여 올바른 메서드를 선택할 수 있도록 합니다. 또한 런타임에 바인딩된 클라이언트는 IDispatch::GetIdsOfNames를 호출할 수 있습니다. 이때 데코레이션된 이름을 전달하여 오버로드된 메서드의 DispID를 가져옵니다.

속성

관리되는 클래스와 인터페이스는 속성을 가질 수 있습니다. 관리되는 속성은 관련된 get 메서드와 set 메서드를 포함하는 특정 데이터 형식을 가집니다. 이 메서드는 다른 메서드와 마찬가지로 개별적으로 정의됩니다. 다음 코드 예제에서는 Height 속성을 포함하는 인터페이스를 보여 줍니다. 인터페이스를 구현하는 클래스는 속성에 대해 get 및 set 메서드를 제공해야 합니다.

    interface IMammal {
 
    IMammal Mother{get;set;}
    IMammal Father{get;set;}
    int     Height{get;set;}
    int     Weight{get;set;}

    }

    class Human : IMammal
    {
        int weight;
        int height;
        IMammal father;
        IMammal mother;

        public IMammal Mother { get { return mother; } set { mother = value; } }
        public IMammal Father { get { return father; } set { father = value; } }
        public int Height { get { return height; } set { height = value; } }
        public int Weight { get { return weight; } set { weight = value; } }
    }

내보내는 동안 Tlbexp.exe는 속성의 set 메서드를 [propput]로 변환하고 get 메서드를 [propget]로 변환합니다. COM의 속성 이름은 관리되는 속성 이름과 동일하게 유지됩니다. 이 규칙에는 다음과 같은 몇 가지 예외가 있습니다.

  • 값 형식을 제외한 속성 형식이 클래스 또는 인터페이스인 경우 속성의 set 메서드는 간접 참조 수준이 추가된 매개 변수를 지정하여 [propputref]가 됩니다.

  • 속성에 get 또는 set 메서드가 없는 경우 Tlbexp.exe는 형식 라이브러리에서 속성을 생략합니다.

속성과 마찬가지로 관리되는 필드도 형식 라이브러리로 내보냅니다. 런타임 마샬링 서비스는 모든 공용 필드에 대해 자동으로 get 메서드와 set 메서드를 생성합니다. 다음 형식 라이브러리 표현에 나타난 것과 같이 변환 프로세스 동안 Tlbexp.exe는 각 필드에 대해 [propput](또는 [propputref]) 함수와 [propget] 함수를 생성합니다.

형식 라이브러리 표현

interface IMammal : IDispatch {
         [propget]    HRESULT Mother([out, retval] IMammal** pRetVal);
         [propputref] HRESULT Mother([in] IMammal* pRetVal);
         [propget]    HRESULT Father([out, retval] IMammal** pRetVal);
         [propputref] HRESULT Father([in] IMammal* pRetVal);
         [propget]    HRESULT Height([out, retval] long* pRetVal);
         [propput]    HRESULT Height([in] long pRetVal);
         [propget]    HRESULT Weight([out, retval] long* pRetVal);
         [propput]    HRESULT Weight([in] long pRetVal);
         [propget]    HRESULT Age([out, retval] long* pRetVal);
         [propput]    HRESULT Age([in] long pRetVal);    
};

이벤트

COM interop의 이벤트 모델 개념에 대해 잘 모르면 관리되는 이벤트와 관리되지 않는 이벤트를 참조하십시오. 관리되는 형식은 대리자 기반 이벤트 모델을 사용하여 이벤트를 구현합니다. 예를 들어 다음 코드 예제의 Class1Events 인터페이스는 Click 이벤트를 발생시킵니다.

    Public Delegate Sub ClickDelegate()
    <GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967"), _
    InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)>

    Public Interface Class1Event
        Sub Click ()
    End Interface
<ComSourceInterfaces("Class1Event, EventSrc")> _
    Public Class Class1
        Public Event Click As ClickDelegate
   End Class
    public delegate void Click();

    public interface Class1Event
    {
        void Click();
    }
   [ComSourceInterfaces("Class1Event, EventSrc")]
    public class Class1
    {
        public event ClickDelegate Click;
    }

내보내는 동안 Tlbexp.exe는 이벤트 인터페이스를 해당 coclass에서 소스로 표시합니다. 다음 형식 라이브러리 표현에서 보는 것처럼 ComClass1Events 인터페이스는 소스 인터페이스로 표시됩니다.

형식 라이브러리 표현

    disinterface Class1Event {
        properties:
        methods:
        [id(0x60020000)]
        HRESULT Click();
    };

    coclass Class1
    {
    …
    [default, source] Class1Event;
    };

참고 항목

개념

내보낸 어셈블리 변환

내보낸 모듈 변환

내보낸 형식 변환

내보낸 매개 변수 변환

기타 리소스

어셈블리를 형식 라이브러리로 변환 요약