Share via


インポート時の型の変換

このトピックでは、インポート プロセスが次の型をどのように変換するかを説明します。

  • インターフェイス

  • Classes

  • 構造体

  • 列挙型

  • 定数

  • Typedef

通常、Tlbimp.exe は、元のタイプ ライブラリ内での名前と同じ名前を付けて型をインポートします。 タイプ ライブラリ内の名前は一意である必要があります。これにより、変換プロセス中の競合を防止できます。 有効なタイプ ライブラリ名はすべて、有効なアセンブリ名になります。

インポートされた型は、その型が属する名前空間によってスコープ設定されます。名前空間の名前は、元のタイプ ライブラリと同じ名前です。 型は、それぞれの型の完全な名前空間と型名によって個別に識別されます。

タイプ ライブラリ内でタイプ ライブラリ属性を使用することにより、インポートする型のマネージ名を明示的に制御できます。 このユーザー定義の属性の ID は、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 に変換されます。

インターフェイス

インポート プロセスがインターフェイスを変換するときは、すべての IUnknown メソッドおよび IDispatch メソッドを除去します。 インターフェイスがデュアル (IDispatch から派生するインターフェイス) でない場合、変換プロセスは、インターフェイスに GuidAttribute を適用して、タイプ ライブラリ内で割り当てられているインターフェイス ID (IID: Interface Identifier) と InterfaceTypeAttribute を保持します。

s8sdycxx.collapse_all(ja-jp,VS.110).gifタイプ ライブラリ表現

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

変換中にインポート プロセスは、基本インターフェイスのメソッドを派生インターフェイスに追加します。 IGadget インターフェイスに New インターフェイスおよび Start インターフェイスを追加する例を次に示します。

<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();
};

Classes

インポート プロセスは、各 COM コクラスを表現するマネージ クラスを作成し、そのマネージ クラスに、元のコクラスの名前に Class を追加した名前を付けます。 たとえば、NewNewer コクラスは NewNewerClass となります。 変換プロセスは、そのクラスに GuidAttribute を追加して、コクラスのクラス ID (CLSID) をキャプチャします。

マネージ クラスだけでなく、インポート プロセスはコクラスと同じ名前を持つインターフェイスを追加し、元のコクラスの CLSID を識別するための CoClassAttribute を適用します。 このインターフェイスは、コクラスの既定のインターフェイスと同じ IID を持ちます。 このインターフェイスを使用すると、クライアントは常にイベント シンクとして登録できます。

COM のコクラスとは異なり、マネージ クラスには、クラス メンバーを含めることができます。 .NET Framework のアプローチとの関係を維持しながら、変換プロセスは、コクラスによって実装された各インターフェイスに関連付けられているメンバーを各クラスに追加します。 マネージ クラスのユーザーは、マネージ型のメソッドとプロパティをあらかじめ特定のインターフェイスにキャストせずに、呼び出すことができます。 また、インポート プロセスは、変換された各コクラスに既定のコンストラクターを追加します。 コンストラクターは、マネージ コードからクラスを作成できるようにします。 コンストラクターのないクラスは、作成できません。 既定のコンストラクターには引数はありません。既定のコンストラクターの実装は、基本クラスのコンストラクターを呼び出します。 コクラスに noncreatable タイプ ライブラリ属性が適用されている場合は、インポート プロセスは、そのクラスに対して既定のコンストラクターを作成しません。

インターフェイス メンバー名は、必ずしも一意ではないため、メンバー間で名前や DispId の衝突が発生する場合があります。 TlbImp.exe は、クラスの衝突する各メンバー名の前に、インターフェイス名とアンダースコア (_) を付けて、名前の衝突を解決します。 メンバー名が衝突するときは、コクラス ステートメントで先にリストされているインターフェイスの名前が変更されずに残ります。

DispId の衝突が発生した場合、インポート プロセスは、コクラスの既定インターフェイスのメンバーに DispId を割り当て、衝突しているクラス メンバーには何も割り当てません。 ただし、インポート プロセスは、常に、インターフェイスのメンバーに DispId を割り当てます。

s8sdycxx.collapse_all(ja-jp,VS.110).gifタイプ ライブラリ表現

[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

タイプ ライブラリ内の型定義 (typedef) は、インポートされません。 代わりに、パラメーターとフィールドが元になる型としてインポートされます。 たとえば、BUTTON_COLOR 型のパラメーターは、BUTTON_COLOR が整数のエイリアスなので、整数型としてインポートされます。

インポートされた後、パラメーターやフィールドは、それらのパラメーターやフィールドを元の型と関連付ける情報を ComAliasNameAttribute で保持します。 変換プロセスは、ComAliasNameAttribute を適用して、フィールド、パラメーター、または戻り値をタイプ ライブラリの名前とライブラリ内でエイリアスとして使用されていた型に関連付けます。

次のタイプ ライブラリ表現は、パラメーター cl が、整数のエイリアスである BUTTON_COLOR 型であることを示しています。

s8sdycxx.collapse_all(ja-jp,VS.110).gifタイプ ライブラリ表現

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 属性を与えられます。 この変換プロセスは、クラス メソッドの引数にも属性を適用します。

参照

概念

インポート時のライブラリの変換

インポート時のモジュールの変換

インポート メンバーの変換

インポート パラメーターの変換

その他の技術情報

タイプ ライブラリからアセンブリへの変換の要約