WINAPI和CALLBACK這兩個(gè)宏 WINAPI和CALLBACK這兩個(gè)宏有什么區(qū)別呢?
_stdcall _cdecl _pascal _fastcall這些關(guān)鍵字是什么意思,有什么區(qū)別呢?
首先看MSDN里給出的解釋,不過(guò)有些語(yǔ)焉不詳哦
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.
再看看到底這兩個(gè)宏的內(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等一些可能很少見(jiàn)的關(guān)鍵字
那么cdecl、pascal、stdcall、fastcall等修飾符號(hào)到底什么意思呢?
非常簡(jiǎn)單,就是關(guān)于堆棧的一些說(shuō)明,首先是函數(shù)參數(shù)壓棧順序,其次是
壓入堆棧的內(nèi)容由誰(shuí)來(lái)清除,調(diào)用者還是函數(shù)自己?
這些開(kāi)關(guān)用來(lái)告訴編譯器產(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
簡(jiǎn)單說(shuō)明:
__cdecl是C/C++和MFC程序默認(rèn)使用的調(diào)用約定,也可以在函數(shù)聲明時(shí)加上__cdecl關(guān)鍵字來(lái)手工指定。采用__cdecl約定時(shí),函數(shù)參
數(shù)按照從右到左的順序入棧,并且由調(diào)用函數(shù)者把參數(shù)彈出棧以清理堆棧。因此,實(shí)現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定。由于每一個(gè)使用__cdecl約定的
函數(shù)都要包含清理堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會(huì)比較大。__cdecl可以寫(xiě)成_cdecl。
__stdcall調(diào)用約定用于調(diào)用Win32 API函數(shù)。采用__stdcal約定時(shí),函數(shù)參數(shù)按照從右到左的順序入棧,被調(diào)用的函
數(shù)在返回前清理傳送參數(shù)的棧,函數(shù)參數(shù)個(gè)數(shù)固定。由于函數(shù)體本身知道傳進(jìn)來(lái)的參數(shù)個(gè)數(shù),因此被調(diào)用的函數(shù)可以在返回前用一條ret n指令直接清理傳遞參
數(shù)的堆棧。__stdcall可以寫(xiě)成_stdcall。
__fastcall約定用于對(duì)性能要求非常高的場(chǎng)合。__fastcall約定將函數(shù)的從左邊開(kāi)始的兩個(gè)大小不大于4個(gè)字節(jié)
(DWORD)的參數(shù)分別放在ECX和EDX寄存器,其余的參數(shù)仍舊自右向左壓棧傳送,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的堆棧。__fastcall可
以寫(xiě)成_fastcall。
·特別說(shuō)明
1. 在默認(rèn)情況下,采用__cdecl方式,因此可以省略.
2. WINAPI一般用于修飾動(dòng)態(tài)鏈接庫(kù)中導(dǎo)出函數(shù)
3. CALLBACK僅用于修飾回調(diào)函數(shù)
4. 你可能已經(jīng)發(fā)現(xiàn),VC下和BCB下對(duì)WINAPI的定義不同,那么你至少理解了
為什么不能直接從BCB下調(diào)用VC的dll的一個(gè)原因了。