__Stdcall क्या है?


151

मैं Win32 प्रोग्रामिंग के बारे में सीख रहा हूं, और WinMainप्रोटोटाइप जैसा दिखता है:

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

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

#define WINAPI      __stdcall

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


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

जवाबों:


170

__stdcallफ़ंक्शन के लिए कॉलिंग कन्वेंशन का उपयोग किया जाता है। यह संकलक को नियम बताता है जो स्टैक स्थापित करने के लिए लागू होता है, तर्कों को आगे बढ़ाता है और रिटर्न वैल्यू प्राप्त करता है।

अन्य बुला सम्मेलनों के एक नंबर रहे हैं, __cdecl, __thiscall, __fastcallऔर शानदार नामित __declspec(naked)__stdcallWin32 सिस्टम कॉल के लिए मानक कॉलिंग कन्वेंशन है।

विकिपीडिया विवरण को कवर करता है ।

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


8
इस प्रश्न को बहुत ही स्टर्नज क्रैश के उदाहरण के लिए देखें stackoverflow.com/questions/696306/…
शार्प्यूट

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

क्या हम कह सकते हैं कि यह कुछ अवैध अनुकूलन को निष्क्रिय कर देगा?
केसरी

40

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

विकिपीडिया लेख वहाँ पता चला विभिन्न बुला सम्मेलनों के एक सिंहावलोकन प्रदान करता है।


18

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


12

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


3
और यह _standard_call के साथ भ्रमित नहीं होना चाहिए कि यह मानक-सी है! एक सोच सकते हैं कि __stdcall की बात हो सकता है अगर एक does not बेहतर जानते हैं
litb - Johannes Schaub

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

आप सही हे। इसे एक CRT फ़ंक्शन की तरह देखा जाता है, लेकिन यह एक API है। किसी भी संयोग से आप जानते हैं कि इसे C # से P / Invoke कैसे करें?
विंडोज प्रोग्रामर

मैंने इसका परीक्षण नहीं किया है, लेकिन pinvoke.net इस हस्ताक्षर को देता है: "स्थिर बाहरी int wsprintf ([आउट] StringBuilder lpOut, string lpFmt, ...);"
माइकल बुर 4

मेरा अंतर्ज्ञान कहता है कि C # कंपाइलर उस पर __cdecl कन्वेंशन का उपयोग करना नहीं जानता होगा।
विंडोज प्रोग्रामर


5

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

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


4

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

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

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

यहाँ fnname ने इसे सीधे स्टैक में धकेल दिया है।


1

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

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

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

ExecuteCommand फ़ंक्शन इसे कॉल करने के लिए startthreadex के लिए विधि हस्ताक्षर में __stdcall कीवर्ड का उपयोग करना चाहिए :

unsigned int __stdcall Scene::ExecuteCommand(void* command)
{
    return system(static_cast<char*>(command));
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.