관리되지 않는 호출 규칙

호출 규칙은 호출자와 호출된 메서드 간에 메서드 인수와 반환 값이 전달되는 방법에 대한 낮은 수준의 세부 정보를 설명합니다.

P/Invoke 선언에 선언된 관리되지 않는 호출 규칙이 네이티브 구현에서 사용되는 관리되지 않는 호출 규칙과 일치해야 합니다. 관리되지 않는 호출 규칙의 불일치로 인해 진단하려면 낮은 수준의 디버깅 기술이 필요한 데이터 손상 및 치명적인 크래시가 발생합니다.

플랫폼 기본 호출 규칙

대부분의 플랫폼은 하나의 정식 호출 규칙을 사용하며 대부분의 경우 명시적으로 지정된 호출 규칙은 필요하지 않습니다.

x86 아키텍처의 경우 기본 호출 규칙은 플랫폼별로 다릅니다. Stdcall("표준 호출")은 Windows x86의 기본 호출 규칙이며 대부분의 Win32 API에서 사용됩니다. Cdecl은 Linux x86의 기본 호출 규칙입니다. Unix에서 시작된 오픈 소스 라이브러리의 Windows 포트는 Windows x86에서도 Cdecl 호출 규칙을 사용하는 경우가 많습니다. 이러한 라이브러리와의 interop를 위해서 P/Invoke 선언에서 Cdecl 호출 규칙을 명시적으로 지정해야 합니다.

x86이 아닌 아키텍처의 경우 StdcallCdecl 호출 규칙은 모두 정식 플랫폼 기본 호출 규칙으로 처리됩니다.

관리 P/Invoke 선언에서 호출 규칙 지정

호출 규칙은 System.Runtime.CompilerServices 네임스페이스의 형식이나 그 조합으로 지정됩니다.

명시적으로 지정된 호출 규칙의 예:

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

참고 항목