2008-11-18 9 views
119

मैं Win32 प्रोग्रामिंग के बारे में सीख रहा हूँ, और WinMain प्रोटोटाइप लगता है:__stdcall क्या है?

int WINAPI WinMain (HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show) 

मैं उलझन में था कि इस WINAPI पहचानकर्ता के लिए था और पाया:

#define WINAPI  __stdcall 

इस क्या करता है? मैं इस प्रकार से उलझन में हूं कि रिटर्न प्रकार के बाद कुछ भी हो रहा है। __stdcall के लिए क्या है? रिटर्न प्रकार और फ़ंक्शन नाम के बीच कुछ होने पर इसका क्या अर्थ है?

+1

@AndrewProck "डमी" परिवर्तन इस मामले में ठीक था, लेकिन आम तौर पर आप मूर्खतापूर्ण (और काउंटर-उत्पादक - मामले में मामले) 6 वर्ण न्यूनतम प्राप्त करने के लिए ' ' का उपयोग कर सकते हैं। –

उत्तर

137

__stdcall बुला समारोह के लिए इस्तेमाल किया सम्मेलन है। यह कंपाइलर नियमों को बताता है जो स्टैक स्थापित करने, तर्कों को धक्का देने और वापसी मूल्य प्राप्त करने के लिए लागू होते हैं।

कई अन्य कॉलिंग सम्मेलन, __cdecl, __thiscall, __fastcall और आश्चर्यजनक नाम __naked हैं। __stdcall Win32 सिस्टम कॉल के लिए मानक कॉलिंग सम्मेलन है।

विकिपीडिया details शामिल किया गया।

यह मुख्य रूप से मायने रखती है जब आप अपने कोड के बाहर एक समारोह (जैसे एक OS एपीआई) बुला रहे हैं या ओएस बुला रहा है (जैसा भी मामला WinMain के साथ यहाँ है)। यदि कंपाइलर सही कॉलिंग सम्मेलन को नहीं जानता है तो आपको शायद बहुत अजीब दुर्घटनाएं मिलेंगी क्योंकि स्टैक सही ढंग से प्रबंधित नहीं किया जाएगा।

+8

इस सवाल को बहुत कठोर दुर्घटनाओं के उदाहरण के लिए देखें http://stackoverflow.com/questions/696306/run-time-check-failure-0-loading-queryfullprocessimagename-from-kernel32-dll – sharptooth

+0

यदि मुझे गलत नहीं है, तो ये कॉलिंग सम्मेलन नियंत्रित करते हैं कि संकलक असेंबली कोड कैसे उत्पन्न करता है। असेंबली कोड के साथ इंटरफेसिंग करते समय, यह तब महत्वपूर्ण है कि कॉलिंग सम्मेलन को स्टैक मुद्दों को रोकने के लिए ध्यान दिया जाता है। कुछ सम्मेलनों को दस्तावेज करने में यहां एक अच्छी तालिका है: https://msdn.microsoft.com/en-us/library/984x0h58.aspx –

+0

क्या हम कह सकते हैं कि इससे कुछ अवैध अनुकूलन अक्षम हो जाएंगे? – kesari

5

यह कैसे समारोह मूल रूप से जिस क्रम में बातें ढेर पर रख दिया और जो सफाई के लिए जिम्मेदार है रहे हैं called- है के साथ क्या करना है।

यहाँ प्रलेखन है, लेकिन यह ज्यादा मतलब नहीं है जब तक कि आप पहले भाग को समझने:
http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx

31

सी या सी ++ ही उन पहचानकर्ता परिभाषित नहीं करते। वे कंपाइलर एक्सटेंशन हैं और कुछ कॉलिंग सम्मेलनों के लिए खड़े हैं। यह निर्धारित करता है कि तर्क कहां रखना है, किस क्रम में, कहलाए गए फ़ंक्शन को रिटर्न पता मिलेगा, और इसी तरह। उदाहरण के लिए, __fastcall का अर्थ है कि कार्यों के तर्क रजिस्टरों पर पारित किए जाते हैं।

Wikipedia Article वहां मिले विभिन्न कॉलिंग सम्मेलनों का एक सिंहावलोकन प्रदान करता है।

15

उत्तर अब तक विवरण शामिल हैं, लेकिन यदि आप असेंबली में उतरने का इरादा नहीं रखते हैं, तो आपको केवल यह जानना होगा कि कॉलर और कैली दोनों को एक ही कॉलिंग सम्मेलन का उपयोग करना चाहिए, अन्यथा आप ' उन बग्स मिलेंगे जो खोजने में मुश्किल हैं।

9

मैं मानता हूं कि अब तक के सभी उत्तर सही हैं, लेकिन यहां कारण है। माइक्रोसॉफ्ट के सी और सी ++ कंपाइलर्स एक एप्लीकेशन के सी और सी ++ कार्यों के भीतर फ़ंक्शन कॉल की (इच्छित) गति के लिए विभिन्न कॉलिंग सम्मेलन प्रदान करते हैं। प्रत्येक मामले में, कॉलर और कैली को इस बात पर सहमत होना चाहिए कि किस कॉलिंग सम्मेलन का उपयोग करना है। अब, विंडोज़ स्वयं ही फ़ंक्शंस (एपीआई) प्रदान करता है, और उनको पहले ही संकलित कर दिया गया है, इसलिए जब आप उन्हें कॉल करते हैं तो आपको उनका पालन करना होगा। विंडोज एपीआई के लिए कोई भी कॉल, और विंडोज एपीआई से कॉलबैक, को __stdcall सम्मेलन का उपयोग करना चाहिए।

+2

और इसे _standard_call के साथ भ्रमित नहीं किया जाना चाहिए कि यह मानक-सी है! कोई ऐसा सोच सकता है कि __stdcall का बिंदु होगा यदि कोई बेहतर नहीं जानता –

+2

एक छोटा नाइटपिक: कुछ विंडोज एपीआई हैं जो __stdcall के बजाय __cdecl का उपयोग करते हैं - आमतौर पर वे जो पैरामीटर की चर संख्या को लेते हैं, जैसे wsprintf()। –

+0

आप सही हैं। यह एक सीआरटी समारोह की तरह दिखने के लिए नामित है लेकिन यह एक एपीआई है। किसी भी मौके से आप जानते हैं कि इसे सी # से पी/कैसे आमंत्रित करें? –

4

__stdcall का उपयोग स्टैक में फ़ंक्शन तर्क डालने के लिए किया जाता है। फ़ंक्शन के पूरा होने के बाद यह स्वचालित रूप से स्मृति को हटा देता है। यह निश्चित तर्कों के लिए प्रयोग किया जाता है।

void __stdcall fnname (int, int*) 
{ 
    ... 
} 

int main() 
{ 
    CreateThread (NULL, 0, fnname, int, int*......) 
} 

यहाँ fnname आर्ग यह सीधे ढेर में धक्का है।

http://www.codeproject.com/KB/cpp/calling_conventions_demystified.aspx

9

पर एक नज़र डालें। इसका कारण यह है कि मेरे कोड में मैं बहु-थ्रेडिंग और बहु-थ्रेडिंग एपीआई का उपयोग कर रहा हूं जिसका उपयोग मैं कर रहा हूं विंडोज़ एक है (_beginthreadex)।

धागा शुरू करने के लिए:

_beginthreadex(NULL, 0, ExecuteCommand, currCommand, 0, 0); 

ExecuteCommand समारोह MUST beginthreadex के लिए आदेश में विधि हस्ताक्षर में __stdcall कीवर्ड का उपयोग इसे कहते हैं:

unsigned int __stdcall Scene::ExecuteCommand(void* command) 
{ 
    return system(static_cast<char*>(command)); 
} 
1

मैं आज तक पहले इस का इस्तेमाल किया था कभी नहीं:

संबंधित मुद्दे