呼叫慣例 描述方法自變數和傳回值在呼叫端與所呼叫方法之間傳遞方式的低階詳細數據。
請務必在 P/Invoke 宣告中宣告的 Unmanaged 呼叫慣例符合原生實作所使用的 Unmanaged 呼叫慣例。 Unmanaged 呼叫慣例中的不相符會導致資料損毀,以及需要低階偵錯能力才能診斷的致命當機。
平台預設呼叫慣例
大部分的平台都會使用一個標準呼叫慣例,而且在大部分情況下,不需要明確指定的呼叫慣例。
針對 x86 架構,預設的呼叫慣例是平臺特定的。
Stdcall (“標準呼叫”) 是 Windows x86 上的預設呼叫慣例,大部分的 Win32 API 都會使用它。
Cdecl 是 Linux x86 上的預設呼叫慣例。 Windows 上的開源程式庫常常是自 Unix移植而來,即使在 Windows x86 系統上,它們也會使用 Cdecl 呼叫規約。 您必須在 P/Invoke 宣告中明確指定 Cdecl 呼叫慣例,以便與這些程式庫進行互操作。
針對非 x86 架構, Stdcall 和 Cdecl 呼叫慣例都會被視為標準平台預設呼叫慣例。
在 Managed P/Invoke 宣告中指定呼叫慣例
呼叫慣例是由命名空間中的 System.Runtime.CompilerServices 型別或其組合所指定:
- CallConvCdecl
- CallConvFastcall
- CallConvMemberFunction
- CallConvStdcall
- CallConvSuppressGCTransition
- CallConvThiscall
明確指定的呼叫慣例範例:
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();
在舊版 .NET 中指定呼叫慣例
.NET Framework 和 .NET 5 之前的 .NET 版本僅限於可由 CallingConvention 列舉所描述的呼叫慣例子集。
明確指定的呼叫慣例範例:
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);