天天看點

WINAPI和CALLBACK這兩個宏有什麼差別

WINAPI和CALLBACK這兩個宏有什麼差別呢?

_stdcall _cdecl _pascal _fastcall這些關鍵字是什麼意思,有什麼差別呢?

首先看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.

再看看到底這兩個宏的内容是什麼吧

VC:WINDEF.h

#define CALLBACK    PASCAL //=_pascal,VC已經不支援直接使用_pascal了

#define WINAPI      CDECL //=_cdecl

BCB:windef.h

#define CALLBACK    __stdcall

#define WINAPI      __stdcall

引出了cdecl stdcall等一些可能很少見的關鍵字

那麼cdecl、pascal、stdcall、fastcall等修飾符号到底什麼意思呢?

非常簡單,就是關于堆棧的一些說明,首先是函數參數壓棧順序,其次是

壓入堆棧的内容由誰來清除,調用者還是函數自己?

這些開關用來告訴編譯器産生什麼樣的彙編代碼。

下面把差別清單如下:

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程式預設使用的調用約定,也可以在函數聲明時加上__cdecl關鍵字來手工指定。采用__cdecl約定時,函數參數按照從右到左的順序入棧,并且由調用函數者把參數彈出棧以清理堆棧。是以,實作可變參數的函數隻能使用該調用約定。由于每一個使用__cdecl約定的函數都要包含清理堆棧的代碼,是以産生的可執行檔案大小會比較大。__cdecl可以寫成_cdecl。

        __stdcall調用約定用于調用Win32 API函數。采用__stdcal約定時,函數參數按照從右到左的順序入棧,被調用的函數在傳回前清理傳送參數的棧,函數參數個數固定。由于函數體本身知道傳進來的參數個數,是以被調用的函數可以在傳回前用一條ret n指令直接清理傳遞參數的堆棧。__stdcall可以寫成_stdcall。

        __fastcall約定用于對性能要求非常高的場合。__fastcall約定将函數的從左邊開始的兩個大小不大于4個位元組(DWORD)的參數分别放在ECX和EDX寄存器,其餘的參數仍舊自右向左壓棧傳送,被調用的函數在傳回前清理傳送參數的堆棧。__fastcall可以寫成_fastcall。

·特别說明

1. 在預設情況下,采用__cdecl方式,是以可以省略.

2. WINAPI一般用于修飾動态連結庫中導出函數

3. CALLBACK僅用于修飾回調函數

4. 你可能已經發現,VC下和BCB下對WINAPI的定義不同,那麼你至少了解了

   為什麼不能直接從BCB下調用VC的dll的一個原因了。 

繼續閱讀