2010-08-04 10 views
6

Quels sont les facteurs clés pour utiliser différentes conventions d'appel? Quand quelqu'un sait-il utiliser des conventions d'appel spécifiques telles que __cdecl ou __stdcall ou __fastcall à différentes occasions.Quand utiliser les conventions d'appel

Les exemples seraient vraiment appréciés.

Répondre

12

La plupart du temps, vous n'avez pas besoin de vous en préoccuper. Habituellement, vous utiliserez __cdecl, mais seulement parce que c'est la valeur par défaut dans Visual C++. Les fonctions membres C++, cependant, utilisent la convention __thiscall par défaut dans Visual C++

Une situation (plutôt commune) où vous devez vraiment vous préoccuper des conventions d'appel est lorsque vous passez des rappels aux fonctions de l'API, comme celles de l'API Windows:

// CALLBACK is #define'd as __stdcall 
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg 
    WPARAM wParam, LPARAM lParam); 
// ... 
windowClass.lpfnWndProc = &MyWndProc; 
::RegisterClass(&windowClass); 

ici, nous déclarons MyWndProc() comme ayant la convention __stdcall (CALLBACK est #define « d comme __stdcall). Cela est nécessaire car le système d'exploitation s'attend à ce que lpfnWndProc pointe vers un WNDPROC, which uses the CALLBACK convention.

À peu près toutes les fonctions API de Windows qui accepte un rappel exige que les fonctions de rappel à utiliser la convention __stdcall, et depuis __cdecl est généralement la valeur par défaut, vous devez faire ce explicite (vous pouvez utiliser CALLBACK pour les procédures de la fenêtre).

Ceci est extrêmement important car la corruption de la pile peut se produire si le système d'exploitation tente d'appeler une fonction non __stdcall. Malheureusement, assez de gens se trompent que Windows will actually check for calling convention mismatch specifically for window procedures. Si __stdcall est requis pour les fonctions de rappel passées aux fonctions WinAPI, les fonctions acceptant un nombre variable d'arguments doivent utiliser la convention d'appel __cdecl, car seul l'appelant saura comment retirer correctement le nombre variable d'arguments de la pile. Comme __cdecl est généralement la valeur par défaut, vous n'avez pas besoin de spécifier explicitement __cdecl pour les fonctions acceptant un nombre variable d'arguments.

Personnellement, je n'ai pas trouvé une utilisation pour __fastcall, mais je suis sûr que quelqu'un l'a.

__clrcall est pertinent uniquement si vous interagissez avec du code managé.