看到的不錯(cuò)的學(xué)習(xí)文章,轉(zhuǎn)帖過來方便自己學(xué)習(xí),無意侵犯作者。只當(dāng)學(xué)習(xí)用
__cdecl
|
__stdcall
|
C 和 C++ 程序的缺省調(diào)用規(guī)范
|
為了使用這種調(diào)用規(guī)范,需要你明確的加上 __stdcall (或 WINAPI )文字。即 return-type __stdcall function-name[(argument-list)]
|
在被調(diào)用函數(shù) (Callee) 返回后,由調(diào)用方 (Caller) 調(diào)整堆棧。
1. 調(diào)用方的函數(shù)調(diào)用
2. 被調(diào)用函數(shù)的執(zhí)行
3. 被調(diào)用函數(shù)的結(jié)果返回
4. 調(diào)用方清除調(diào)整堆棧
|
在被調(diào)用函數(shù) (Callee) 返回前,由被調(diào)用函數(shù) (Callee) 調(diào)整堆棧。圖示:
1. 調(diào)用方的函數(shù)調(diào)用
2. 被調(diào)用函數(shù)的執(zhí)行
3. 被調(diào)用函數(shù)清除調(diào)整堆棧
4. 被調(diào)用函數(shù)的結(jié)果返回
|
因?yàn)槊總€(gè)調(diào)用的地方都需要生成一段調(diào)整堆棧的代碼,所以最后生成的文件較大。
|
因?yàn)檎{(diào)整堆棧的代碼只存在在一個(gè)地方(被調(diào)用函數(shù)的代碼內(nèi)),所以最后生成的文件較小。
|
函數(shù)的參數(shù)個(gè)數(shù)可變(就像 printf 函數(shù)一樣),因?yàn)橹挥姓{(diào)用者才知道它傳給被調(diào)用函數(shù)幾個(gè)參數(shù),才能在調(diào)用結(jié)束時(shí)適當(dāng)?shù)卣{(diào)整堆棧。
|
函數(shù)的參數(shù)個(gè)數(shù)不能是可變的。
|
對于定義在 C 程序文件中的輸出函數(shù),函數(shù)名會保持原樣,不會被修飾。
對于定義在 C++ 程序文件中的輸出函數(shù),函數(shù)名會被修飾, MSDN 說 Underscore character (_) is prefixed to names . 我實(shí)際測試( VC4 和 VC6 )下來發(fā)現(xiàn)好像不是那么簡單。
可通過在前面加上 extern “C” 以去除函數(shù)名修飾。也可通過 .def 文件去除函數(shù)名修飾。
|
不論是 C 程序文件中的輸出函數(shù)還是 C++ 程序文件中的輸出函數(shù),函數(shù)名都會被修飾。
對于定義在 C 程序文件中的輸出函數(shù), An underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list.
對于定義在 C++ 程序文件中的輸出函數(shù),好像更復(fù)雜,和 __cdecl 的情況類似。
好像只能通過 .def 文件去除函數(shù)名修飾。
|
_beginthread 需要 __cdecl 的線程函數(shù)地址
|
_beginthreadex 和 CreateThread 需要 __stdcall 的線程函數(shù)地址
|
兩者的參數(shù)傳遞順序都是從右向左。
為了讓 VB 可以調(diào)用,需要用 __stdcall 調(diào)用規(guī)范來定義 C/C++ 函數(shù)。請參看Microsoft KB153586 文章:How To Call C Functions That Use the _cdecl Calling Convention。
當(dāng)你 LoadLibrary 一個(gè) DLL 文件后, 把 GetProcAddress 取得的函數(shù)地址傳給上面三個(gè)線程生成函數(shù)時(shí),請務(wù)必確認(rèn)實(shí)際定義在 DLL 文件的輸出函數(shù)符合調(diào)用規(guī)范要求。否則,編譯成 Release 版后運(yùn)行,可能會破壞堆棧,程序行為不可預(yù)測。
VC 中的相關(guān)編譯開關(guān):/Gd /Gr /Gz。另外,VC6中新增加的 /GZ 編譯開關(guān)可以幫你檢查堆棧問題。
我也是初學(xué)者,若有不對的地方、可以補(bǔ)充的地方,請指教。謝謝。
|