1. 程式人生 > >WinAPI WinMain, CreateMutex, ShellExecute三個函數

WinAPI WinMain, CreateMutex, ShellExecute三個函數

運行 關鍵字 ipc windows應用 消息 msd 大小 似的 dll

WinMain函數是提供給用戶的Windows應用程序入口點,其原型如下:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ipCmdLine, int nCmdShow);

函數有四個參數:

hInstancd: 是當前應用長須實例的Handle。

hPrevInstance: 是應用程序上一個實例的Handle。(MSDN:如果你想要知道程序是否有另一個實例,建議使用Mutex來實現,用Mutex可以實現只運行一個實例)

ipCmdLine: 字符串,是命令行參數。

nCmdShow: int型,指明windows應該怎麽實現,windows定義了一系列的宏來幫助記憶,以SW開頭,如:SW_SHOW。

返回值是一個int型。

如果函數運行成功的話,它會一直運行,知道接收到WM_QUIT消息,它應該返回消息的wParam參數的退出值。如果函數進入消息循環前退出,它應該返回0。

WINAPI 是一個宏定義:

#define WINAPI __stdcall

__stdcall和__cdecl, __pascal, __fastcall都是一些類似的關鍵字,詳細信息如下:

1.它們實際上是關於堆棧的一些說明,包括函數參數壓棧順序和壓入堆棧的內容由誰來清除(是調用者還是自己)。而上述這些關鍵字用來告訴編譯器產生什麽樣的匯編代碼。

2.VC由兩種函數的調用方式:__stdcall和__cdecl

前者指的是PASCAL調用方式,後者指的時C調用方式。使用PASCAL調用方式,函數在返回到調用者之間將參數從棧中刪除;使用C調用方式,參數的刪除是調用者完成的。

WinMain函數由系統調用,windows系統規定由系統調用的函數都要遵循PASCAL調用方式,但是VC中函數的缺省調用方式是C調用方式,所以要在WinMain前顯式聲明WINAPI。在Windows編程中將會遇到很多類似的聲明,如:CALLBACK, WINAPI, PASCAL這些在Intel CPU的計算機上都是__stdcall。

3.__cdecl是C/C++和MFC程序默認使用的調用方式,也可以在函數聲明時加上__cdecl關鍵字來手動指定。采用__cdecl調用方式時,函數的參數按照從右到左的順序入棧,並且由函數調用者把參數彈出棧以清理堆棧,因此,實現可變參數的函數只能使用該調用方式,由於每一個使用__cdecl調用方式的函數都要包含清理堆棧的代碼,所以產生的可執行文件的大小會比較大;__stdcall調用方式用於調用win32 API函數,采用__stdcal調用方式時,函數參數按照從右到左的順序入棧,被調用的函數在返回前清理傳送參數的棧,函數參數個數固定,由於函數體本身知道傳進來的參數個數,因此被調用的函數可以在返回前用一條ret n指令直接清理傳遞參數的堆棧;__fastcall調用方式用於對性能要求非常高,__fastcall調用方式將函數的從左邊開始的兩個大小不大於4個字節(DWORD)的參數分別放在ECX和EDX寄存器,其余的參數仍舊自右向左壓棧傳送,被調用的函數在返回前清理傳送參數的堆棧。

thiscall僅僅用於"C++"成員函數。this指針存放在CX/ECX寄存器中,參數從右到左壓。thiscall不是關鍵字,因此不能被程序員指定。

nakedcall。當采用其他調用方式時,如果必要的話,進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數時則產生代碼恢復這些寄存器的內容。

特別說明:

  1.在默認情況下,采用__cdecl方式,因此可以省略。

  2.WINAPI一般用於修飾動態鏈接庫中導出的函數。

  3.CALLBACK僅用於修飾回調函數。

  4.你可能已經發現,VC下和BCB下對WINAPI的定義不同,那麽你至少理解為什麽不能直接從BCB下調用VC的DLL的一個原因了。

總體來說,VC默認的是__cdecl方式,Win32 API函數是用__stdcall方式的,他們都是將函數的參數從右到左入棧的,__cdecl方式的每個函數都有清理堆棧的代碼,可以實現可變參數列表,但可執行文件比較大。__stdcall方式是調用方式是調用者清理堆棧的。__fastcall的特點是他講參數左邊的兩個參數放在寄存器上,比較快。其余參數還是在堆棧中,堆棧還是由函數自己清理。

WinAPI WinMain, CreateMutex, ShellExecute三個函數