web-dev-qa-db-fra.com

Qu'est-ce que __stdcall?

J'apprends la programmation Win32 et le prototype WinMain ressemble à ceci:

int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )

J'étais confus quant à la raison pour laquelle cet identifiant WINAPI était:

#define WINAPI      __stdcall

Qu'est-ce que cela fait? Je suis dérouté par le fait que quelque chose se passe après un type de retour. Quel est __stdcall pour? Qu'est-ce que cela signifie quand il y a quelque chose entre le type de retour et le nom de la fonction?

136
Tristan Havelick

__stdcall est la convention d'appel utilisée pour la fonction. Ceci indique au compilateur les règles qui s'appliquent pour configurer la pile, pousser des arguments et obtenir une valeur de retour.

Il existe un certain nombre d'autres conventions d'appel, __cdecl, __thiscall, __fastcall et le merveilleusement nommé __naked. __stdcall est la convention d'appel standard pour les appels système Win32.

Wikipedia couvre le détails .

Cela importe principalement lorsque vous appelez une fonction en dehors de votre code (par exemple, une API de système d'exploitation) ou que le système d'exploitation vous appelle (comme c'est le cas ici avec WinMain). Si le compilateur ne connaît pas la convention d'appel correcte, vous aurez probablement des plantages très étranges car la pile ne sera pas gérée correctement.

157
Rob Walker

C ou C++ lui-même ne définissent pas ces identificateurs. Ce sont des extensions de compilateur et représentent certaines conventions d'appel. Cela détermine où placer les arguments, dans quel ordre, où la fonction appelée trouvera l'adresse de retour, etc. Par exemple, __fastcall signifie que les arguments des fonctions sont passés sur les registres.

Le Article Wikipedia fournit un aperçu des différentes conventions d'appel trouvées.

36

Jusqu'à présent, les réponses ont couvert les détails, mais si vous n'avez pas l'intention de passer à l'Assemblée, vous devez simplement savoir que l'appelant et l'appelé doivent utiliser la même convention d'appel, sinon vous obtiendrez des bugs sont difficiles à trouver.

16
MovEaxEsp

Je conviens que toutes les réponses à ce jour sont correctes, mais voici la raison. Les compilateurs C et C++ de Microsoft fournissent diverses conventions d’appel pour la vitesse (prévue) des appels de fonction dans les fonctions C et C++ d’une application. Dans chaque cas, l'appelant et l'appelé doivent s'entendre sur la convention d'appel à utiliser. Maintenant, Windows lui-même fournit des fonctions (API) et celles-ci ont déjà été compilées. Vous devez donc vous y conformer lorsque vous les appelez. Tous les appels aux API Windows et les rappels à partir des API Windows doivent utiliser la convention __stdcall.

10
Windows programmer
10
MojeSmece

Cela a à voir avec la façon dont la fonction est appelée - en gros, l'ordre dans lequel les choses sont mises sur la pile et qui est responsable du nettoyage.

Voici la documentation, mais cela ne veut pas dire grand chose à moins de comprendre la première partie:
http://msdn.Microsoft.com/en-us/library/zxk0tw93.aspx

5
Joel Coehoorn

__stdcall est utilisé pour placer les arguments de la fonction dans la pile. Une fois la fonction terminée, il libère automatiquement la mémoire. Ceci est utilisé pour les arguments fixes.

void __stdcall fnname ( int, int* )
{
    ...
}

int main()
{
    CreateThread ( NULL, 0, fnname, int, int*...... )
}

Ici, le nom de fichier a l'argument de le placer directement dans la pile.

4
Rajesh Manem

Je n'ai jamais eu à l'utiliser avant aujourd'hui. C'est parce que dans mon code j'utilise le multi-threadding et que l'API multi-thread que j'utilise est celle de Windows (_beginthreadex).

Pour démarrer le fil:

_beginthreadex(NULL, 0, ExecuteCommand, currCommand, 0, 0);

La fonction ExecuteCommand DOIT utiliser le mot clé __stdcall dans la signature de la méthode pour que beginthreadex puisse l'appeler:

unsigned int __stdcall Scene::ExecuteCommand(void* command)
{
    return system(static_cast<char*>(command));
}
1
Katianie