次の方法で共有


.NET 相互運用での暗黙的なメソッドシグネチャ変換

プログラミング言語に依存しないようにするために、Windows COM システムと多くの Windows API は、API が成功したか失敗したかを示すために、 HRESULT と呼ばれる 4 バイトの整数型と、エラーに関する情報を返します。 呼び出し元に渡す必要があるその他の値は、"out" パラメーターとして機能するポインター パラメーターを介して "返される" ものであり、通常はシグネチャの最後のパラメーターです。 C# や Visual Basic などの言語は、従来、エラー コードを例外に変換して、エラーが通常言語で伝達される方法と一致し、相互運用メソッドシグネチャに HRESULTが含まれていないことが想定されています。 メソッド シグネチャをネイティブ シグネチャに変換するために、ランタイムはメソッドの戻り値を追加の "out" パラメーターに移動し、もう 1 つのレベルの間接参照 (つまり、マネージド シグネチャの戻り値の型へのポインター) に移動し、 HRESULT 戻り値を想定します。 マネージド メソッドが voidを返す場合、追加のパラメーターは追加されておらず、戻り値は HRESULTになります。 たとえば、同じネイティブ シグネチャに変換する次の 2 つの C# COM メソッドを参照してください。

int Add(int a, int b);

void Add(int a, int b, out int sum);
HRESULT Add(int a, int b, /* out */ int* sum);

COM での PreserveSig

C# のすべての COM メソッドでは、既定で翻訳されたシグネチャが使用されることが想定されています。 HRESULT値のシグネチャ変換と処理なしでメソッドを使用およびエクスポートするには、を COM インターフェイス メソッドに追加します。 属性がメソッドに適用されている場合、シグネチャへの変換は行われず、 HRESULT 値が失敗しても例外はスローされません。 これは、組み込みの COM とソースで生成された COM の両方に適用されます。 たとえば、 PreserveSig 属性とそれに対応するネイティブ シグネチャを持つ次の C# メソッド シグネチャを参照してください。

[PreserveSig]
int Add(int a, int b, out int sum);
HRESULT Add(int a, int b, int* sum);

これは、メソッドがエラーではないが、異なる方法で処理する必要がある異なる HRESULT 値を返す可能性がある場合に便利です。 たとえば、一部のメソッドでは、失敗せずに部分的な結果だけを返す場合にS_FALSEの値を返し、すべての結果を返す場合にS_OKの値を返すことがあります。

PreserveSig P/Invokes を使用する

DllImportAttribute属性には、bool PreserveSigと同様に動作するPreserveSigAttribute フィールドもありますが、既定値は true です。 ランタイムがマネージド署名を変換し、返されるHRESULTを処理することを示すには、PreserveSig フィールドをfalseDllImportAttributeに設定します。 たとえば、同じネイティブ メソッドに対する 2 つの P/Invoke の次のシグネチャを参照してください。1 つは PreserveSigfalse に設定され、1 つは既定の true 値に残されています。

[DllImport("shlwapi.dll", EntryPoint = "SHAutoComplete", ExactSpelling = true, PreserveSig = false)]
public static extern void SHAutoComplete(IntPtr hwndEdit, SHAutoCompleteFlags dwFlags);

[DllImport("shlwapi.dll", EntryPoint = "SHAutoComplete", ExactSpelling = true)]
public static extern int SHAutoCompleteHRESULT(IntPtr hwndEdit, SHAutoCompleteFlags dwFlags);

LibraryImportAttributeを使用するソース生成 P/Invoke には、PreserveSigフィールドがありません。 生成されたコードでは、ネイティブ署名とマネージド 署名が常に同一であると想定されます。 詳細については、「 ソース生成 P/Invokes」を参照してください。

HRESULT値を手動で処理する

PreserveSigを返すHRESULT メソッドを呼び出すときに、ThrowExceptionForHRがエラーを示している場合は、HRESULT メソッドを使用して対応する例外をスローできます。 同様に、 PreserveSig メソッドを実装する場合は、 GetHRForException メソッドを使用して、例外の対応する値を示す HRESULT を返すことができます。

HRESULT を構造体としてマーシャリング

PreserveSig メソッドを使用する場合、intHRESULTのマネージド型であることが期待されます。 ただし、戻り値の型としてカスタムの 4 バイト構造体を使用すると、 HRESULTの操作を簡略化できるヘルパー メソッドとプロパティを定義できます。 組み込みのマーシャリングでは、これは自動的に機能します。 ソース生成マーシャリングでintのマネージド表現としてHRESULTの代わりに構造体を使用するには、引数としてMarshalAsAttributeを持つError属性を追加します。 この属性が存在すると、 HRESULT のビットが構造体として再解釈されます。

こちらも参照ください