Windows API セット

重要

このトピックの情報は、Windows 10 以降のすべてのバージョンに適用されます。 ここでは、これらのバージョンを Windows と呼び、必要に応じて例外を呼び出します。

すべてのバージョンの Windows は、コア OS と呼ばれるオペレーティング システム (OS) コンポーネントの共通ベースを共有します (一部のコンテキストでは、この共通ベースは OneCore とも呼ばれます)。 コア OS コンポーネントでは、Win32 API は API セットと呼ばれる機能グループに編成されます。

API セットの目的は、特定の Win32 API が実装されているホスト DLL と、API が属する機能コントラクトの間でアーキテクチャ上の分離を提供することです。 API セットが実装とコントラクトの間で提供する分離は、開発者にとって多くのエンジニアリング上の利点となります。 特に、コードで API セットを使用すると、Windows デバイスとの互換性が向上します。

具体的には、API セットは以下のシナリオを扱います。

  • Win32 API の完全な幅は PC でサポートされていますが、HoloLens、XBOX、その他のデバイスなどの他のWindows デバイスでは、Win32 API のサブセットのみが使用できます。 API セット名を使用すると、アプリが現在のデバイスで機能を使用できるかどうかを実行時に検出できるように、安定した質問を行うことができます。 クエリ自体は 、IsApiSetImplemented 関数によって実行されます。

  • 一部の Win32 API 実装は、異なる Windows デバイス間で異なる名前を持つ DLL に存在します。 API の可用性と遅延読み込み API を検出するときに DLL 名の代わりに API セット名を使用すると、API が実際に実装されている場所に関係なく、実装への正しいルートが提供されます。

詳細については、API セット ローダー操作API セットの可用性の検出に関するページを参照してください。

API セットと DLL は同じですか?

いいえ— API セット名は、ファイルではなく コントラクトを識別します。 実行時に、ローダーは現在のデバイスの API セット スキーマを介してそのコントラクトを解決し、実装をホストする DLL への参照をルーティングします。 これは実装を隠す手法で、呼び出し元は、どのモジュールが情報をホストしているのかを正確に知る必要はありません。

この手法を使用すると、異なる Windows バージョンやエディションでモジュールをリファクタリング (分割、統合、名前変更など) できます。 アプリは引き続きリンクされ、実行時に正しいコードにルーティングされます。

では、なぜ API セットの名前には .dll が含まれているのでしょうか。 その理由は、DLL ローダーの実装方法です。 ローダーは、DLL を読み込んだり、DLL への参照を解決したりする OS の一部であり、インポート テーブルでファイル名のスペルを指定したモジュール名によって読み込む内容を識別します。 API セット名は、同じ場所に収まるように同じ規則に従います。

ローダーは、 api- または ext- で始まる名前を認識し、 それを API セット ランタイム (スキーマを介してコントラクトを解決するローダーの拡張機能) にルーティングします。 その時点から、名前はファイル名ではなく API セットの名前付け規則によって解析されるため、 .dll サフィックスは解決されるコントラクト名の一部ではありません。

API セット名を LoadLibrary に渡すか、遅延読み込みターゲットとして使用できます。 この操作は、現在のデバイス上のスキーマがそのコントラクトを使用可能なホストにマップすると成功します。PC 上のどこにも、その名前の実際のファイルが存在するとは限りません。 コントラクトが現在のデバイスにマップされていない場合、直接 LoadLibrary は失敗します。 遅延読み込み参照の動作は異なります。プロセスは引き続き読み込まれ、不在は後で API が呼び出されたときに表面化します。

いずれの場合も、リンクまたは読み込みが成功しても、実装が存在するという証拠はそれ自体ではありません。 そのことを確認するには、「 API セットの可用性の検出」を参照してください。

アンブレラ ライブラリのリンク

コア OS でサポートされている Win32 API にコードを簡単に制限できるように、一連の アンブレラ ライブラリが用意されています。 アンブレラ ライブラリを使用すると、呼び出す API ごとに個別のインポート ライブラリを識別する代わりに、1 つのライブラリをリンクできます。

詳細については、対象と一致するアンブレラ ライブラリを選択するには、アンブレラ ライブラリWindows参照してください。

API セット コントラクト名

API セットは、ライブラリ ローダーによって認識される規則に従うコントラクト名によって識別されます。

すべてのコントラクト名は、次の規則を共有します。

  • 名前は、文字列 api または ext で始まります。
  • 名前の本文には、英数字またはダッシュ (-) を指定できます。 チルダ (~) は、グループ名の前の区切り記号としてのみ表示されます。
  • 名前の大文字と小文字は区別されます。

コントラクト名の 2 つの形式が使用されており、いずれか 1 つに遭遇することができます。

バージョン管理されたコントラクト名は、シーケンス l<n>-<n>-<n> で終わります。n は 10 進数 (たとえば、ext-ms-win-core-samplefeature-l1-1-0) で構成されます。 末尾の番号はコントラクトの特定のバージョンを識別します。この形式の名前は、そのバージョンの不変識別子と見なす必要があります。

コントラクトエイリアスには、api-win-core-samplefeatureなどのバージョンはありません。 1 つのバージョンではなく、コントラクト自体を識別します。 コントラクトが個別に使用可能な機能を 名前付きグループに整理すると、グループ名をコントラクトエイリアスに追加して、チルダ : api-win-core-samplefeature~AdvancedOperationsで区切ってグループがアドレス指定されます。

ここで使用するsamplefeature名は、架空のWindows コンポーネントのわかりやすい名前です。

api プレフィックスと ext- プレフィックス

プレフィックスは名前付け規則です。 もともとは、すべての対象エディション (api-) に存在するコントラクトと、存在しない可能性があるコントラクト (ext-) を区別することを目的としていました。 この区別は一貫して適用されず、コントラクトのロールは、コントラクトの名前が変更されずに時間の経過と同時に変更される可能性があります。

ローダーはプレフィックスに有意性を割り当てない。API 名とext- 名は同じ規則で解決されます。 プレフィックスから可用性を推測しないでください。 代わりにクエリを実行します。 API セットの可用性を検出するを参照してください。

コントラクト名の使用

コントラクト名を指定する操作には、2種類あります。

LoadLibraryP/Invoke などのローダー操作は、DLL モジュール名が通常表示されるのと同じ場所でコントラクト名を取得します。 追加された .dll は、そのコンテキストでは従来の方法ですが、API セットの名前解決では必須ではなく、コントラクト名の一部ではありません。 物理 DLL モジュール名の代わりにコントラクト名を使用して、現在のデバイスで API が実際に実装されている場所に関係なく、実装への正しいルートを確保します。 そのコントラクト名を持つファイルがディスク上に存在する必要はありません。

可用性クエリの例では 、従来、 .dll サフィックスを省略し、API のアドレス指定方法に一致する形式を使用します。

API の公開範囲 クエリ フォーム
名前付きグループ <contract>~<group> api-win-core-samplefeature~AdvancedOperations
既定のグループ ~Default のないコントラクトエイリアス api-win-core-samplefeature
バージョン付き契約 バージョン付きコントラクトの完全名 ext-ms-win-core-samplefeature-l1-1-0

グループ名をバージョン管理されたコントラクト名と組み合わせることはできません。

Win32 API の API セットの識別

特定の Win32 API が API セットに属しているかどうかを特定するには、API のリファレンス ドキュメントの要件表を確認します。 API が API セットに属している場合は、記事の要件表に API セット名と、API セットに最初に導入された Windows バージョンが一覧表示されます。 API セットに属する API の例については、次の記事を参照してください。

API のヘッダーが Is<APIName>Present ヘルパー関数を提供する場合は、可用性をテストするときにそのヘルパーを使用します。 API を含む API セットまたはグループの正しい名前が既に含まれています。 詳細については、 API セットの可用性の検出に関するページを参照してください。

このセクション内