Share via


Impliciete vertalingen van methodehandtekening in .NET-interop

Om de programmeertaal neutraal te houden, retourneren het Windows COM-systeem en veel Windows-API's een 4 byte integertype genaamd HRESULT een om aan te geven of een API is geslaagd of mislukt, samen met enkele informatie over de fout. Andere waarden die aan de aanroeper moeten worden doorgegeven, worden 'geretourneerd' via aanwijzerparameters die fungeren als 'out'-parameters en zijn meestal de laatste parameter in de handtekening. Talen zoals C# en Visual Basic vertalen traditioneel een foutcode naar een uitzondering zodat deze overeenkomt met de manier waarop fouten meestal worden doorgegeven in de taal, en verwachten dat handtekeningen van de interop-methode het HRESULTniet bevatten. Als u de methodehandtekening wilt vertalen naar een systeemeigen handtekening, verplaatst de runtime de retourwaarde van de methode naar een extra 'out'-parameter met een extra indirectieniveau (met andere woorden, wordt deze een aanwijzer naar het retourtype van de beheerde handtekening) en wordt een retourwaarde aangenomen HRESULT . Als de beheerde methode retourneert void, wordt er geen extra parameter toegevoegd en wordt de retourwaarde een HRESULT. Zie bijvoorbeeld de volgende twee C#COM-methoden die worden vertaald naar dezelfde systeemeigen handtekening:

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

Voor alle COM-methoden in C# wordt standaard de vertaalde handtekening gebruikt. Als u methoden wilt gebruiken en exporteren zonder de handtekeningomzetting en -verwerking van HRESULT waarden, voegt u de PreserveSigAttribute methode toe aan een COM-interfacemethode. Wanneer het kenmerk wordt toegepast op een methode, wordt er geen vertaling naar de handtekening uitgevoerd en worden er geen uitzonderingen gegenereerd voor mislukte HRESULT waarden. Dit is van toepassing op zowel ingebouwde COM als op bron gegenereerde COM. Zie bijvoorbeeld de volgende C#-methodehandtekening met een PreserveSig kenmerk en de bijbehorende systeemeigen handtekening.

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

Dit kan handig zijn als de methode verschillende HRESULT waarden retourneert die geen fouten zijn, maar anders moet worden verwerkt. Sommige methoden kunnen bijvoorbeeld de waarde S_FALSE retourneren wanneer een methode niet mislukt, maar alleen gedeeltelijke resultaten retourneert en S_OK wanneer alle resultaten worden geretourneerd.

PreserveSig met P/Invokes

Het DllImportAttribute kenmerk heeft ook het bool PreserveSig veld dat op dezelfde manier werkt als de PreserveSigAttribute, maar is standaard ingesteld trueop . Als u wilt aangeven dat de runtime de beheerde handtekening moet vertalen en de HRESULT geretourneerde handtekening moet verwerken, stelt u het PreserveSig veld in op het DllImportAttributeveld false . Zie bijvoorbeeld de volgende handtekeningen van twee P/Invokes naar dezelfde systeemeigen methode, één met PreserveSig ingesteld op falseen één met de standaardwaarde 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);

Notitie

Door de bron gegenereerde P/Invokes, die gebruikmaken van het LibraryImportAttributeveld, hebben geen PreserveSig veld. Bij de gegenereerde code wordt ervan uitgegaan dat de systeemeigen en beheerde handtekening identiek zijn. Zie brongegenereerde P/Invokes voor meer informatie.

Waarden handmatig verwerken HRESULT

Wanneer u een methode aanroept die een PreserveSigHRESULTretourneert, kunt u de ThrowExceptionForHR methode gebruiken om de bijbehorende uitzondering te genereren als de HRESULT fout aangeeft. Bij het implementeren van een PreserveSig methode kunt u ook de GetHRForException methode gebruiken om de HRESULT methode te retourneren die een overeenkomstige waarde voor de uitzondering aangeeft.

Marshal HRESULTs as structs

Wanneer u een PreserveSig methode gebruikt, int is dit naar verwachting het beheerde type voor HRESULT. Met behulp van een aangepaste 4-byte-struct als het retourtype kunt u echter helpermethoden en eigenschappen definiëren die het werken met de HRESULT. In ingebouwde marshalling werkt dit automatisch. Als u een struct wilt gebruiken in plaats van int de beheerde weergave van HRESULT door de bron gegenereerde marshalling, voegt u het MarshalAsAttribute kenmerk toe met Error als het argument. De aanwezigheid van dit kenmerk herinterpreteert de bits van de HRESULT struct.

Zie ook