アンマネージド呼び出し規則
呼び出し規則では、呼び出し元と呼び出されたメソッドの間でメソッドの引数と戻り値を渡す方法の、下位レベルの詳細について説明します。
P/Invoke 宣言で宣言されたアンマネージド呼び出し規則が、ネイティブ実装で使用されるアンマネージド呼び出し規則と一致することが重要です。 アンマネージド呼び出し規則の不一致により、データの破損や致命的なクラッシュが発生します。これには診断に低レベルのデバッグ スキルが必要です。
プラットフォーム既定の呼び出し規則
ほとんどのプラットフォームでは 1 つの正規の呼び出し規則が使用され、ほとんどの場合、明示的に指定された呼び出し規則は不要です。
x86 アーキテクチャの場合、既定の呼び出し規則はプラットフォーム固有です。 Stdcall
("標準呼び出し") は Windows x86 の既定の呼び出し規則であり、ほとんどの Win32 API で使用されます。 Cdecl
は Linux x86 の既定の呼び出し規則です。 Unix で発生したオープン ソース ライブラリの Windows ポートでは、Windows x86 でも Cdecl
呼び出し規則が使用されることがよくあります。 これらのライブラリとの相互運用のために、P/Invoke 宣言で Cdecl
呼び出し規則を明示的に指定する必要があります。
x86 以外のアーキテクチャの場合、Stdcall
呼び出し規則と Cdecl
呼び出し規則の両方が、標準プラットフォームの既定の呼び出し規則として扱われます。
マネージド 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 5 より前のバージョンの .NET Framework と .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);
関連項目
.NET