¿Qué es__stdcall?
winapi calling-convention (8)
Estoy aprendiendo acerca de la programación de Win32, y el prototipo de WinMain
ve así:
int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )
Estaba confundido en cuanto a para qué era este identificador de WINAPI
y lo encontré:
#define WINAPI __stdcall
¿Qué hace esto? Estoy confundido por tener algo después de un tipo de devolución. ¿ __stdcall
qué sirve __stdcall
? ¿Qué significa cuando hay algo entre el tipo de devolución y el nombre de la función?
C o C ++ en sí mismo no definen esos identificadores. Son extensiones de compilador y representan ciertas convenciones de llamadas. Eso determina dónde colocar los argumentos, en qué orden, dónde la función llamada encontrará la dirección de retorno, y así sucesivamente. Por ejemplo, __fastcall significa que los argumentos de las funciones se pasan por los registros.
El details proporciona una descripción general de las diferentes convenciones de llamadas que se encuentran por ahí.
Estoy de acuerdo en que todas las respuestas hasta ahora son correctas, pero esta es la razón. Los compiladores C y C ++ de Microsoft proporcionan varias convenciones de llamadas para la velocidad (prevista) de llamadas a funciones dentro de las funciones C y C ++ de una aplicación. En cada caso, la persona que llama y la persona que llama deben acordar qué convención de llamadas usar. Ahora, Windows mismo proporciona funciones (API), y esas ya han sido compiladas, por lo que cuando las llame debe cumplirlas. Todas las llamadas a las API de Windows y las devoluciones de llamadas de las API de Windows deben usar la convención __stdcall.
Las respuestas hasta ahora han cubierto los detalles, pero si no tiene la intención de bajar al montaje, todo lo que debe saber es que tanto la persona que llama como la persona que llama deben usar la misma convención de llamadas, de lo contrario, obtendrá errores que son difíciles de encontrar
Nunca tuve que usar esto antes hasta hoy. Es porque en mi código estoy usando multi-threadding y la API multi-threading que estoy usando es la de Windows (_beginthreadex).
Para comenzar el hilo:
_beginthreadex(NULL, 0, ExecuteCommand, currCommand, 0, 0);
La función ExecuteCommand DEBE usar la palabra clave __stdcall en la firma del método para que beginthreadex la llame:
unsigned int __stdcall Scene::ExecuteCommand(void* command)
{
return system(static_cast<char*>(command));
}
Tiene que ver con cómo se llama a la función, básicamente el orden en que las cosas se ponen en la pila y quién es responsable de la limpieza.
Aquí está la documentación, pero no significa mucho a menos que comprenda la primera parte:
http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx
__stdcall se usa para poner los argumentos de la función en la pila. Después de completar la función, automáticamente desasigna la memoria. Esto se usa para argumentos fijos.
void __stdcall fnname ( int, int* )
{
...
}
int main()
{
CreateThread ( NULL, 0, fnname, int, int*...... )
}
Aquí el fnname tiene args que directamente empuja hacia la pila.
__stdcall
es la convención de llamadas utilizada para la función. Esto le dice al compilador las reglas que se aplican para configurar la pila, empujar los argumentos y obtener un valor de retorno.
Hay una serie de otras convenciones de llamadas, __cdecl
, __thiscall
, __fastcall
y el nombre maravilloso __naked
. __stdcall
es la convención de llamadas estándar para llamadas al sistema Win32.
Wikipedia cubre los details .
Principalmente importa cuando llama a una función fuera de su código (por ejemplo, una API de sistema operativo) o el sistema operativo lo está llamando (como es el caso aquí con WinMain). Si el compilador no conoce la convención de llamada correcta, es probable que obtenga bloqueos muy extraños, ya que la pila no se gestionará correctamente.