2010-08-04 18 views
6

Quali sono i fattori chiave nell'utilizzo di convenzioni di chiamata diverse? Quando qualcuno sa di utilizzare convenzioni di chiamata specifiche come __cdecl o __stdcall o __fastcall in diverse occasioni.Quando utilizzare le convenzioni di chiamata

Esempi sarebbero davvero apprciati.

risposta

12

La maggior parte delle volte non è necessario preoccuparsi. Solitamente userete __cdecl, ma solo perché è l'impostazione predefinita in Visual C++. Le funzioni membro C++, tuttavia, utilizzano la convenzione __thiscall per impostazione predefinita in Visual C++

Una situazione (piuttosto comune) in cui si deve davvero preoccuparsi di chiamare le convenzioni quando si passano i callback alle funzioni API, come quelle dell'API di Windows:

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

Qui, dichiariamo MyWndProc() ad avere la __stdcall convenzione (CALLBACK è #define 'd come __stdcall). Questo è necessario perché il sistema operativo si aspetta che lpfnWndProc punti a WNDPROC, which uses the CALLBACK convention.

Quasi ogni funzione API di Windows che accetta un callback richiede le funzioni di callback per utilizzare la convenzione __stdcall, e dal momento che è di solito __cdecl il default, è necessario rendere questo esplicito (si usa CALLBACK per le procedure di finestra).

Questo è estremamente importante perché il danneggiamento dello stack può verificarsi se il sistema operativo tenta di chiamare una funzione non __stdcall. Sfortunatamente la gente ha sbagliato questo Windows will actually check for calling convention mismatch specifically for window procedures.

Mentre è necessario il __stdcall per le funzioni di callback passate alle funzioni WinAPI, le funzioni che accettano un numero variabile di argomenti devono utilizzare la convenzione di chiamata __cdecl, poiché solo il chiamante saprà come estrarre correttamente il numero variabile di argomenti dallo stack. Dal momento che l'impostazione predefinita è __cdecl, non è necessario specificare esplicitamente __cdecl per le funzioni che accettano un numero variabile di argomenti.

Personalmente non ho trovato un utilizzo per __fastcall, anche se sono sicuro che qualcuno lo ha.

__clrcall è rilevante solo se si interagisce con il codice gestito.

Problemi correlati