가져온 형식 변환

이 항목에서는 가져오기 프로세스에서 다음 형식을 변환하는 방법을 설명합니다.

  • 인터페이스

  • 클래스

  • 구조체

  • 열거형

  • 상수

  • 형식 정의

일반적으로 Tlbimp.exe는 형식을 가져올 때 해당 형식이 원본 형식 라이브러리에서 사용했던 이름과 같은 이름을 사용합니다. 변환 과정에서 이름 충돌 문제가 발생하지 않도록 형식 라이브러리 내에서 이름이 고유해야 합니다. 유효한 모든 형식 라이브러리 이름은 유효한 어셈블리 이름입니다.

가져온 형식은 해당 형식이 속한 네임스페이스에 의해 범위가 지정되고 원본 형식 라이브러리와 같습니다. 형식은 전체 네임스페이스와 형식 이름으로 각각 식별됩니다.

형식 라이브러리에서 형식 라이브러리 특성을 사용하면 가져온 형식의 관리되는 이름을 명시적으로 제어할 수 있습니다. 이 사용자 정의 특성 식별자는 0F21F359-AB84-41e8-9A78-36D110E6D2F9입니다. 다음 형식 라이브러리는 사용자 정의 특성 추가를 보여 줍니다.

형식 라이브러리 표현

[  uuid(…),
    version(1.0)
]
library AcmeLib {
    interface Widget {};
    [custom(0F21F359-AB84-41e8-9A78-36D110E6D2F9, 
     "Acme.WidgetLib.Slingshot")]
    coclass Slingshot {};
};

Tlbimp.exe가 형식 라이브러리를 AcmeLib 네임스페이스로 가져오지만 Slingshot 클래스는 Acme.WidgetLib.Slingshot이 됩니다.

인터페이스

가져오기 프로세스에서 인터페이스를 변환하는 경우 모든 IUnknownIDispatch 메서드가 제거됩니다. IDispatch에서 파생된 이중 인터페이스가 아닌 경우, 변환은 GuidAttribute를 인터페이스에 적용하여 형식 라이브러리에서 할당된 IID(인터페이스 식별자)와 InterfaceTypeAttribute를 유지합니다.

형식 라이브러리 표현

[uuid(…), ]
interface IWidget : IUnknown {
    HRESULT New()
    HRESULT Start()
};
[uuid(…), ]
interface IGadget : IWidget {
    HRESULT Baz()
};

변환하는 동안 가져오기 프로세스는 기본 인터페이스의 메서드를 파생 인터페이스에 추가합니다. 다음 예제에서는 New와 Start가 IGadget 인터페이스에 추가됩니다.

<Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IWidget
    Sub [New]()
    Sub Start()
End Interface

<Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IGadget
    Inherits IWidget
    Shadows Sub [New]()
    Shadows Sub Start()
    Sub Baz()
End Interface
[Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IWidget {
    void New();
    void Start();
};
[Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IGadget : IWidget {
    new void New();
    new void Start();
    void Baz();
};

클래스

가져오기 프로세스는 관리되는 클래스를 만들어 각 COM coclass를 나타냅니다. 이때 관리되는 클래스의 이름은 원래 coclass 이름에 Class를 붙인 것입니다. 예를 들어, NewNewer coclass는 NewNewerClass가 됩니다. 변환하면 coclass의 CLSID(클래스 식별자)를 캡처할 수 있도록 GuidAttribute가 클래스에 추가됩니다.

관리되는 클래스 외에도, 가져오기 프로세스는 coclass와 이름이 같은 인터페이스를 추가하고 CoClassAttribute에 적용하여 원본 coclass의 CLSID를 식별합니다. 이 인터페이스는 coclass의 기본 인터페이스와 IID가 같습니다. 이 인터페이스를 사용하여 클라이언트는 항상 이벤트 싱크로서 등록될 수 있습니다.

COM coclass와 달리 관리되는 클래스는 클래스 멤버를 포함할 수 있습니다. .NET Framework 접근 방식에 맞추어 변환 과정에서는 coclass에 의해 구현되는 각 인터페이스와 관련된 멤버가 각 클래스에 추가됩니다. 관리되는 클래스 사용자는 먼저 특정 인터페이스로 캐스팅하지 않고 관리되는 형식의 메서드와 속성을 호출할 수 있습니다. 또한 가져오기 프로세스는 기본 생성자를 변환된 각 coclass에 추가합니다. 생성자를 사용하면 관리 코드에서 클래스를 만들 수 있습니다. 생성자 없이 클래스를 만들 수 없습니다. 기본 생성자에는 인수가 없으며 구현하면 기본 클래스 생성자를 호출합니다. noncreatable 형식 라이브러리 특성이 coclass에 적용되면 가져오기 프로세스에서 클래스의 기본 생성자를 만들지 않습니다.

인터페이스 멤버 이름이 항상 고유한 것은 아니므로 멤버 간에 이름과 DispId가 충돌할 수 있습니다. TlbImp.exe는 클래스에서 충돌하는 각 멤버의 이름 앞에 인터페이스 이름과 밑줄을 추가하여 이름 충돌을 해결합니다. 멤버의 이름이 충돌하는 경우 coclass 문에 처음으로 나오는 인터페이스는 변경되지 않고 그대로 유지됩니다.

DispId 충돌이 일어나는 경우 가져오기 프로세스는 coclass의 기본 인터페이스 멤버에 DispId를 할당하고 충돌하는 클래스 멤버에는 아무 것도 할당하지 않습니다. 그러나 가져오기 프로세스는 항상 인터페이스 멤버에 DispId를 할당합니다.

형식 라이브러리 표현

[uuid(…)]
interface INew : IDispatch {
    [id(0x100)] HRESULT DoFirst();
    [id(0x101)] HRESULT DoSecond();
}
[uuid(…)]
interface INewer : IDispatch {
    [id(0x100)] HRESULT DoNow();
    [id(0x101)] HRESULT DoSecond();
}
[uuid(…)]
coclass NewNewer  {
    [default] interface INew;
    interface INewer;
}

변환된 형식은 다음과 같이 나타납니다.

<Guid(…)> Public Interface INew
    …
End Interface

<Guid(…)> Public Interface INewer
    …
End Interface

<Guid(…)> Public Interface NewNewer
Inherits INew
    …
End Interface

<Guid(…)> Public Class NewNewerClass
Implements INew   
Implements INewer
Implements NewNewer
' Method implementation
     <DispId(100)> _
      …
End Class  
[Guid(…)]
public interface INew {…}

[Guid(…)]
public interface INewer {…}

[Guid(…)]
public interface NewNewer : INew {…}

[Guid(…)]
public class NewNewer : INew, INewer, NewNewer{
// Method implementation.
     [DispId(100)]…
}

구조체

형식 라이브러리 내에 정의된 구조체는 메타데이터로 가져옵니다. 구조체 필드가 참조 형식인 경우 Tlbimp.exe는 형식을 IntPtr로 가져오고 ComConversionLossAttribute를 적용합니다. 특성은 가져오기 프로세스 중에 정보가 손실되었음을 나타냅니다.

열거형

형식 라이브러리 가져오기(Tlbimp.exe)는 관리되지 않는 열거형을 관리되는 Enum 형식으로 가져옵니다.

상수

이번 릴리스에서는 형식 라이브러리에서 상수를 가져오지 않습니다.

형식 정의

형식 라이브러리 내에서 typedef(형식 정의)를 가져오지 않습니다. 대신 매개 변수와 필드를 내부 형식으로 가져옵니다. 예를 들면 BUTTON_COLOR는 정수에 대한 별칭이므로 이 형식의 매개 변수를 형식 정수로 가져옵니다.

일단 가져오고 나면 매개 변수와 필드는 ComAliasNameAttribute를 사용하여 원본 형식과 자신을 연결시키는 정보를 전달합니다. 변환 프로세스는 ComAliasNameAttribute를 적용하여 필드, 매개 변수 또는 반환 값을 형식 라이브러리의 이름 및 해당 라이브러리에서 별칭으로 사용했던 형식과 연결시킵니다.

다음 형식 라이브러리 표현에서는 정수에 대한 별칭인 BUTTON_COLOR로 형식화된 cl 매개 변수를 보여 줍니다.

형식 라이브러리 표현

library MyLib {
    typedef [public] int BUTTON_COLOR;

    interface ISee {
        HResult SetColor([in] BUTTON_COLOR cl);
        HResult GetColor([out, retval] BUTTON_COLOR *cl);
    };
   
    coclass See {
        [default] interface ISee
    };
};

변환된 형식은 다음과 같이 나타납니다.

public interface ISee {
    void SetColor([ComAliasName("MyLib.BUTTON_COLOR")]] int cl);
    [return: ComAliasName("MyLib.BUTTON_COLOR")] int GetColor();
};

public class See {
    public void SetColor([ComAliasName("MyLib.BUTTON_COLOR")]] int cl);
    [return: ComAliasName("MyLib.BUTTON_COLOR")] int GetColor();
};

실제 형식 BUTTON_COLOR는 결과 메타데이터에 정의되어 있지 않습니다. 대신 형식 라이브러리에서 BUTTON_COLOR로 형식화된 매개 변수는 int의 내부 형식으로 형식화되고 ComAliasNameAttribute 특성을 사용합니다. 또한 이 변환 프로세스는 클래스 메서드의 인수에 특성을 적용합니다.

참고 항목

개념

가져온 라이브러리 변환

가져온 모듈 변환

가져온 멤버 변환

가져온 매개 변수 변환

기타 리소스

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