Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Las convenciones de llamada describen los detalles de bajo nivel sobre cómo se pasan los argumentos de método y los valores devueltos entre el autor de la llamada y el método llamado.
Es importante que la convención de llamada no administrada declarada en una declaración P/Invoke coincida con la convención de llamada no administrada usada por la implementación nativa. Los desajustes en las convenciones de llamada no gestionadas provocan corrupción de datos y fallos críticos que requieren habilidades de depuración de bajo nivel para diagnosticar.
Convención de llamada predeterminada de la plataforma
La mayoría de las plataformas usan una convención de llamada canónica y una convención de llamada especificada explícitamente no es necesaria en la mayoría de los casos.
Para la arquitectura x86, la convención de llamada predeterminada es específica de la plataforma.
Stdcall ("llamada estándar") es la convención de llamada predeterminada en Windows x86 y la usan la mayoría de las API de Win32. es la convención de llamada predeterminada en Linux x86. Versiones para Windows de bibliotecas de código abierto que se originaron en Unix suelen usar la convención de llamada de Cdecl, incluso en Windows x86. Es necesario especificar explícitamente la convención de llamada en declaraciones P/Invoke para la interoperabilidad con estas bibliotecas.
Para las arquitecturas que no son x86, tanto las convenciones de llamada como se tratan como la convención de llamada predeterminada de la plataforma canónica.
Cuando se puede omitir la convención de llamada
En las arquitecturas x64, ARM y ARM64, solo hay una convención de llamada, por lo que especificar una explícitamente no es necesaria. Solo tiene que especificar una convención de llamada al establecer como destino Windows x86 (32 bits), donde Stdcall y Cdecl difieren.
- ✔️ ESPECIFIQUE explícitamente la convención de llamada al dirigirse a Windows x86.
- ✔️ Omita la convención de llamada en x64, ARM y ARM64; el atributo no tiene ningún efecto en estas arquitecturas.
Especificación de convenciones de llamada en declaraciones P/Invoke administradas
Las convenciones de llamada se especifican mediante tipos en el espacio de nombres o sus combinaciones:
- CallConvCdecl
- CallConvFastcall
- CallConvMemberFunction
- CallConvStdcall
- CallConvSuppressGCTransition
- CallConvThiscall
Ejemplos de convenciones de llamada especificadas explícitamente:
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();
Especificación de convenciones de llamada en versiones anteriores de .NET
.NET Framework y versiones de .NET anteriores a .NET 5 se limitan a un subconjunto de convenciones de llamada que puede describir la enumeración CallingConvention.
Ejemplos de convenciones de llamada especificadas explícitamente:
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);
Consulte también
- Invocación de plataforma (P/Invoke)