Udostępnij za pośrednictwem


Niezarządzane konwencje wywoływania

Konwencje wywoływania opisują szczegóły niskiego poziomu dotyczące sposobu przekazywania argumentów metody i zwracanych wartości między obiektem wywołującym a wywołaną metodą.

Ważne jest, aby niezarządzana konwencja wywoływania zadeklarowana w deklaracji P/Invoke była zgodna z niezarządzaną konwencją wywoływania używaną przez implementację natywną. Niezgodności w niezarządzanych konwencjach wywoływania prowadzą do uszkodzenia danych i krytycznych awarii, które wymagają umiejętności debugowania niskiego poziomu do diagnozowania.

Domyślna konwencja wywoływania platformy

Większość platform używa jednej konwencji kanonicznej wywoływania, a w większości przypadków jawnie określona konwencja wywoływania jest niepotrzebna.

W przypadku architektury x86 domyślna konwencja wywoływania jest specyficzna dla platformy. Stdcall ("wywołanie standardowe") jest domyślną konwencją wywoływania w systemie Windows x86 i jest używana przez większość interfejsów API Win32. Cdecl to domyślna konwencja wywoływania w systemie Linux x86. Porty systemu Windows bibliotek typu open source pochodzące z systemu Unix często używają Cdecl konwencji wywoływania nawet w systemie Windows x86. Należy jawnie określić konwencję Cdecl wywoływania w deklaracjach P/Invoke na potrzeby współdziałania z tymi bibliotekami.

W przypadku architektur innych niż x86 konwencje StdcallCdecl wywoływania są traktowane jako domyślna konwencja wywoływania platformy kanonicznej.

Określanie konwencji wywoływania w zarządzanych deklaracjach P/Invoke

Konwencje wywoływania są określane przez typy w System.Runtime.CompilerServices przestrzeni nazw lub ich kombinacje:

Przykłady jawnie określonych konwencji wywoływania:

using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

// P/Invoke declaration using SuppressGCTransition calling convention.
[LibraryImport("kernel32.dll")]
[UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvSuppressGCTransition) })]
extern static ulong GetTickCount64();

// Unmanaged callback with Cdecl calling convention.
[UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvCdecl) })]
static unsafe int NativeCallback(void* context);

// Method returning function pointer with combination of Cdecl and MemberFunction calling conventions.
static unsafe delegate* unmanaged[Cdecl, MemberFunction]<int> GetHandler();

Określanie konwencji wywoływania we wcześniejszych wersjach platformy .NET

Wersje .NET Framework i .NET wcześniejsze niż .NET 5 są ograniczone do podzestawu konwencji wywoływania, które mogą być opisane przez wyliczenie CallingConvention .

Przykłady jawnie określonych konwencji wywoływania:

using System.Runtime.InteropServices;

// P/Invoke declaration using Cdecl calling convention
[DllImport("ucrtbase.dll", CallingConvention=CallingConvention.Cdecl)]
static void* malloc(UIntPtr size);

// Delegate marshalled as callback with Cdecl calling convention
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void Callback(IntPtr context);

Zobacz też