次の方法で共有


非管理呼び出し規則

呼び出し規則では、呼び出し 元と呼び出されたメソッドの間でメソッドの引数と戻り値を渡す方法の低レベルの詳細について説明します。

P/Invoke 宣言で宣言されたアンマネージ呼び出し規則が、ネイティブ実装で使用されるアンマネージ呼び出し規則と一致することが重要です。 アンマネージド呼び出し規則の不一致により、診断に低レベルのデバッグ スキルが必要なデータの破損や致命的なクラッシュが発生します。

プラットフォームの既定の呼び出し規則

ほとんどのプラットフォームでは 1 つの正規の呼び出し規則が使用され、ほとんどの場合、明示的に指定された呼び出し規則は不要です。

x86 アーキテクチャの場合、既定の呼び出し規則はプラットフォーム固有です。 Stdcall ("標準呼び出し") は、Windows x86 の既定の呼び出し規則であり、ほとんどの Win32 API で使用されます。 は Linux x86 の既定の呼び出し規則です。 Unix で発生したオープンソース ライブラリのWindowsポートでは、Windows x86 でも多くの場合、Cdecl 呼び出し規則が使用されます。 これらのライブラリとの相互運用のために、P/Invoke 宣言で 呼び出し規則を明示的に指定する必要があります。

x86 以外のアーキテクチャの場合、 呼び出し規則と 呼び出し規則の両方が、標準プラットフォームの既定の呼び出し規則として扱われます。

呼び出し規則を省略できる場合

x64、ARM、ARM64 のアーキテクチャでは、呼び出し規則は 1 つだけであるため、明示的に指定する必要はありません。 呼び出し規則は、Windows x86 (32 ビット) を対象とする場合にのみ必要です。StdcallCdeclが異なります。

  • ✔️ x86 を対象とする場合は、Windows の呼び出し規則を明示的に指定してください。
  • ✔️ x64、ARM、ARM64 の呼び出し規則を省略してください。この属性は、これらのアーキテクチャには影響しません。

マネージド P/Invoke 宣言での呼び出し規則の指定

呼び出し規則は、 名前空間の型またはその組み合わせによって指定されます。

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

こちらも参照ください

  • プラットフォーム呼び出し (P/Invoke)