Freigeben über


Implizite Methodensignatur-Übersetzungen in .NET Interop

Um die Programmiersprache neutral zu halten, geben das Windows COM-System und viele Windows-APIs einen 4-Byte-Ganzzahltyp zurück, um anzugeben, ob eine API erfolgreich oder fehlgeschlagen ist, zusammen mit zusätzlichen Informationen zum Fehler. Andere Werte, die an den Aufrufer übergeben werden müssen, werden über Zeigerparameter "zurückgegeben", die als "out"-Parameter fungieren und in der Regel der letzte Parameter in der Signatur sind. Sprachen wie C# und Visual Basic übersetzen traditionell einen Fehlercode in eine Ausnahme, um die übliche Vorgehensweise in der Sprache bei Fehlerweitergabe widerzuspiegeln, und erwarten, dass Interop-Methodensignaturen den HRESULT nicht enthalten. Um die Methodensignatur in eine systemeigene Signatur zu übersetzen, verschiebt die Laufzeit den Rückgabewert der Methode auf einen zusätzlichen "out"-Parameter mit einer weiteren Dereferenzierungsebene (d. h. macht sie zu einem Zeiger auf den Rückgabetyp der verwalteten Signatur), und es wird ein HRESULT Rückgabewert angenommen. Wenn die verwaltete Methode void zurückgibt, wird kein zusätzlicher Parameter hinzugefügt, und der Rückgabewert wird zu einem HRESULT. Sehen Sie sich beispielsweise die folgenden beiden C#-COM-Methoden an, die in dieselbe systemeigene Signatur übersetzt werden:

int Add(int a, int b);

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

PreserveSig in COM

Es wird erwartet, dass alle COM-Methoden in C# standardmäßig die übersetzte Signatur verwenden. Um Methoden ohne Signaturübersetzung und -verarbeitung von HRESULT Werten zu verwenden und zu exportieren, fügen Sie die PreserveSigAttribute Methode einer COM-Schnittstelle hinzu. Wenn das Attribut auf eine Methode angewendet wird, wird keine Übersetzung für die Signatur durchgeführt, und Ausnahmen werden nicht für fehlerhafte HRESULT Werte ausgelöst. Dies gilt sowohl für integrierte COM als auch für von der Quelle generierte COM. Sehen Sie sich beispielsweise die folgende C#-Methodensignatur mit einem PreserveSig Attribut und der entsprechenden nativen Signatur an.

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

Dies kann hilfreich sein, wenn die Methode möglicherweise unterschiedliche HRESULT Werte zurückgibt, die keine Fehler sind, aber unterschiedlich behandelt werden müssen. Beispielsweise können einige Methoden den Wert S_FALSE zurückgeben, wenn eine Methode nicht fehlschlägt, sondern nur Teilergebnisse zurückgibt und S_OK wenn alle Ergebnisse zurückgegeben werden.

PreserveSig mit P/Invokes

Das DllImportAttribute-Attribut verfügt auch über das Feld bool PreserveSig das ähnlich wie das Feld PreserveSigAttribute funktioniert, aber standardmäßig auf true festgelegt ist. Um anzugeben, dass die Laufzeit die verwaltete Signatur übersetzen und das zurückgegebene HRESULT verarbeiten soll, legen Sie das PreserveSig-Feld auf false in der DllImportAttribute. Sehen Sie sich z. B. die folgenden Signaturen von zwei P/Invokes an die gleiche systemeigene Methode an, eine, bei der PreserveSig auf false festgelegt ist, und eine, bei der der Standardwert true bebehalten wird.

[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);

Hinweis

Quellgenerierte P/Invokes, die das LibraryImportAttributeFeld verwenden, weisen kein PreserveSig Feld auf. Der generierte Code geht immer davon aus, dass die systemeigene und verwaltete Signatur identisch ist. Weitere Informationen finden Sie unter "Source-generated P/Invokes".

Manuelles Behandeln von HRESULT Werten

Beim Aufrufen einer PreserveSig-Methode, die ein HRESULT zurückgibt, können Sie die ThrowExceptionForHR-Methode verwenden, um die entsprechende Ausnahme auszulösen, falls HRESULT auf einen Fehler hinweist. Ebenso können Sie bei der Implementierung einer PreserveSig Methode die GetHRForException Methode verwenden, um den HRESULT entsprechenden Wert für die Ausnahme zurückzugeben.

Marshal HRESULTs als Strukturen

Bei der Verwendung einer PreserveSig-Methode wird erwartet, dass int der verwaltete Typ für HRESULT ist. Wenn Sie jedoch eine benutzerdefinierte 4-Byte-Struktur als Rückgabetyp verwenden, können Sie Hilfsmethoden und Eigenschaften definieren, die die Arbeit mit HRESULT vereinfachen. Im integrierten Marshalling funktioniert dies automatisch. Um eine Struktur anstelle von int als die verwaltete Darstellung von HRESULT im quellcodegenerierten Marshalling zu verwenden, fügen Sie das MarshalAsAttribute Attribut mit Error als Argument hinzu. Das Vorhandensein dieses Attributs interpretiert die Bits der HRESULT Als Struktur neu.

Siehe auch