WINAPI和CALLBACK這兩個宏 WINAPI和CALLBACK這兩個宏有什么區(qū)別呢?
_stdcall _cdecl _pascal _fastcall這些關鍵字是什么意思,有什么區(qū)別呢?
首先看MSDN里給出的解釋,不過有些語焉不詳哦
WINAPI
·Use in place of FAR PASCAL in API declarations. If you are writing a DLL with exported API entry points, you can use this for your own APIs.
CALLBACK
·Use in place of FAR PASCAL in application callback routines such as window procedures and dialog procedures.
再看看到底這兩個宏的內(nèi)容是什么吧
VC:WINDEF.h
#define CALLBACK PASCAL //=_pascal,VC已經(jīng)不支持直接使用_pascal了
#define WINAPI CDECL //=_cdecl
BCB:windef.h
#define CALLBACK __stdcall
#define WINAPI __stdcall
引出了cdecl stdcall等一些可能很少見的關鍵字
那么cdecl、pascal、stdcall、fastcall等修飾符號到底什么意思呢?
非常簡單,就是關于堆棧的一些說明,首先是函數(shù)參數(shù)壓棧順序,其次是
壓入堆棧的內(nèi)容由誰來清除,調(diào)用者還是函數(shù)自己?
這些開關用來告訴編譯器產(chǎn)生什么樣的匯編代碼。
下面把區(qū)別列表如下:
Directive Parameter order Clean-up Passes parameters in registers?
register Left-to-right Routine Yes
pascal Left-to-right Routine No
cdecl Right-to-left Caller No
stdcall Right-to-left Routine No
safecall Right-to-left Routine No
簡單說明:
__cdecl是C/C++和MFC程序默認使用的調(diào)用約定,也可以在函數(shù)聲明時加上__cdecl關鍵字來手工指定。采用__cdecl約定時,函數(shù)參
數(shù)按照從右到左的順序入棧,并且由調(diào)用函數(shù)者把參數(shù)彈出棧以清理堆棧。因此,實現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定。由于每一個使用__cdecl約定的
函數(shù)都要包含清理堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會比較大。__cdecl可以寫成_cdecl。
__stdcall調(diào)用約定用于調(diào)用Win32 API函數(shù)。采用__stdcal約定時,函數(shù)參數(shù)按照從右到左的順序入棧,被調(diào)用的函
數(shù)在返回前清理傳送參數(shù)的棧,函數(shù)參數(shù)個數(shù)固定。由于函數(shù)體本身知道傳進來的參數(shù)個數(shù),因此被調(diào)用的函數(shù)可以在返回前用一條ret n指令直接清理傳遞參
數(shù)的堆棧。__stdcall可以寫成_stdcall。
__fastcall約定用于對性能要求非常高的場合。__fastcall約定將函數(shù)的從左邊開始的兩個大小不大于4個字節(jié)
(DWORD)的參數(shù)分別放在ECX和EDX寄存器,其余的參數(shù)仍舊自右向左壓棧傳送,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的堆棧。__fastcall可
以寫成_fastcall。
·特別說明
1. 在默認情況下,采用__cdecl方式,因此可以省略.
2. WINAPI一般用于修飾動態(tài)鏈接庫中導出函數(shù)
3. CALLBACK僅用于修飾回調(diào)函數(shù)
4. 你可能已經(jīng)發(fā)現(xiàn),VC下和BCB下對WINAPI的定義不同,那么你至少理解了
為什么不能直接從BCB下調(diào)用VC的dll的一個原因了。