2010-11-16 23 views
5

मेरे पास एक कक्षा है जिसमें केवल स्थिर सदस्य हैं।सी पुस्तकालयों से कॉलिंग सी ++ फ़ंक्शन पॉइंटर्स

मैं "एटएक्सिट" लाइब्रेरी फ़ंक्शन का उपयोग करके बाहर निकलने के लिए अपने सदस्य फ़ंक्शंस (नीचे दिए गए कोड में VerifyClean) को पंजीकृत करना चाहता हूं।

C++ FQA कहता है कि मुझे उस फ़ंक्शन के लिए बाहरी "सी" निर्दिष्ट करना होगा जिसे मैं इस तरह से पंजीकृत करना चाहता हूं, जैसे कि निम्न उदाहरण में।

class Example 
{ 
public: 
    static void Initialize(); 
    static void DoDirtyStuff {++dirtLevel;} 
    static void CleanUpStuff {--dirtLevel;} 
private: 
    static void VerifyClean(); 
    // DOESN'T COMPILE: extern "C" static void VerifyClean(); 
    static int dirtLevel; 
} 

int Example::dirtLevel; 

extern "C" void Example::VerifyClean() // DO I NEED extern "C" HERE? 
{ 
    assert(dirtLevel == 0); 
} 

void Example::Initialize() 
{ 
    dirtLevel = 0; 
    atexit(&VerifyClean); 
} 

क्या मुझे वास्तव में बाहरी "सी" का उपयोग करना है?

क्या उत्तर बदलता है यदि मैं एक गैर पुस्तकालय समारोह (सादे सी में लागू) के साथ "atexit" को प्रतिस्थापित करता हूं?

यदि फ़ंक्शन VerifyClean सार्वजनिक थे और मैंने इसे सीधे C++ कोड से कॉल करने का निर्णय लिया, तो क्या मुझे लिंक त्रुटियां या रनटाइम क्रैश मिलेगा? मैं यह पूछता हूं क्योंकि घोषणा में बाहरी "सी" का उल्लेख नहीं है, इसलिए नियमित सी ++ कोड फ़ंक्शन कॉल को गलत तरीके से संभाल सकता है। यह मेरे एमएस विजुअल स्टूडियो 2005 सिस्टम पर ठीक काम करता है।

+7

क्यों केवल स्थिर कार्यों के साथ एक वर्ग है ? और एफक्यूए सी ++ के बारे में जानने के लिए शायद ही कोई अच्छी जगह है। –

+6

"FQA माना हानिकारक" – jkerian

+2

सी ++ FQA पूछे जाने वाले प्रश्न से C++ सीखने के लिए एक और अधिक विश्वसनीय स्रोत है। –

उत्तर

7

यह संभव है एक संकलक के लिए सी और सी ++ कोड के लिए विभिन्न कॉलिंग सम्मेलनों का उपयोग करने के लिए; हालांकि, व्यवहार में, यह लगभग कभी नहीं होता है।

तुम सिर्फ यह काम करने के लिए और अस्पष्ट compilers समर्थन के बारे में परवाह नहीं करना चाहते हैं, extern "C" से परेशान नहीं है। किसी भी व्यापक रूप से उपयोग किए गए कंपाइलर में यह आवश्यक नहीं है।

आप पूरी तरह पंडिताऊ हो, या एक पंडिताऊ संकलक समर्थन करने की आवश्यकता चाहते हैं, एक आवरण लिखना:

extern "C" static void ExampleVerifyClean() 
{ 
    Example::VerifyClean(); 
} 

void Example::Initialize() 
{ 
    dirtLevel = 0; 
    atexit(&ExampleVerifyClean); 
} 
+1

+1। बताता है कि यह संभवतः चिंता करने योग्य नहीं है ('atexit (और VerifyClean) 'शायद अभ्यास में काम करेगा), और फिर पिक तकनीकी रूप से सही समाधान देता है। – aschepler

+0

सी ++ कंपाइलर ने फ़ंक्शन का नाम उलझाने के मामले में बाहरी "सी" भी नहीं किया है? या जब अधिकांश सी ++ कंपाइलर्स को मैंगलिंग से बचने की आवश्यकता नहीं होती है (उदाहरण के लिए जब कोई अधिभार नहीं होता है या कार्य कक्षा के अंदर नहीं होते हैं)? –

1

लिंक त्रुटियां।

सी ++ नाम मैंगलिंग कहलाता है, जो प्रकार की जानकारी के साथ एक लिंक-टाइम फ़ंक्शन नाम उत्पन्न करता है।

बाहरी सी से एक सरल पहचानकर्ता में बदल जाता है।

संपादित करें:

सब कुछ एक सी ++ संकलक द्वारा संकलित किया जा रहा है, तो यह एक मुद्दा नहीं होगा। लेकिन अगर आपके पास एक सी कंपाइलर द्वारा संकलित ऑब्जेक्ट फ़ाइल है और एक C++ कंपाइलर द्वारा संकलित किया गया है, तो आपको कुछ समस्याएं होने जा रही हैं।

मैं एक निर्वासन 'सी' विनिर्देश की आवश्यकता होती है DLLs को याद करने लगते हैं, लेकिन है कि स्मृति


ठीक है इस बिंदु पर हो सकता है 10 साल पुराना है।

मैं एक समारोह है कि एक हस्ताक्षर

पूर्णांक foo (नाव, नाव)

था के साथ एक परीक्षण का मामला ऊपर मार पड़ी है और 3 अलग जीसीसी आमंत्रण के तहत यह संकलित -

gcc test_c.c -S 
g++ test.cpp -S 

इन दो चालानों ने असेंबली में विभिन्न पहचानकर्ताओं का उत्पादन किया। सी ++ ने अपने सामान्य प्रकार-संशोधित दृष्टिकोण में नाम को उलझा दिया था। तब

g++ test.cpp -S 

कौन सा तो घायल सी ++ नाम हटाया (बेशक compilers इस अलग तरह से कर सकते हैं)

, मैं Extern "सी" में foo लिपटे और जी ++ फिर से लागू ..., एक सादे छोड़ने सी unmangled नाम।

हालांकि यहां अन्य सूक्ष्मताएं शामिल हैं, उदाहरण के लिए, स्टैक पर धक्का देने वाले तर्कों का क्रम, मैं डेटा के आधार पर इस बिंदु पर अपना मामला आराम करता हूं।

+2

की जरूरत नहीं है –

+1

+1 कुछ मूर्खतापूर्ण, हार्मोन संचालित ड्राइव-डाउनवॉटर द्वारा बिना किसी कारण के डाउनवॉटेड होने के लिए +1। वैसे, 'बाहरी "सी" 'नाम उलझन को बंद नहीं करता है, लेकिन यह * आम तौर पर * अंडरस्कोर का उपसर्ग करने के लिए, एक बहुत ही सरल उलझन में परिणाम देता है। चियर्स, –

+1

@ जॉन: प्रश्न संभव बुला सम्मेलन का मुद्दा यह है कि आप का उल्लेख नाम mangling साथ क्या करना है, और यह भी है। नाम मैंगलिंग का उद्देश्य एक प्रकार का कमजोर लिंक समय प्रकार की जांच करना है (आप इस प्रकार के सम्मेलन भाग को कॉल करने पर विचार कर सकते हैं)। कुछ संकलक एक ही संकलन इकाई में कोड के लिए भी शिकायत करते हैं, हालांकि जहां तक ​​मैं सभी मौजूदा ऐसे कंपाइलरों के लिए जानता हूं चेतावनी बंद कर दी जा सकती है। चीयर्स, –

0
निर्वासन 'सी', अपने कार्य का नाम होगा, संकलक द्वारा घायल हो गया तो समारोह नाम आप क्या उम्मीद से अलग अंत हो सकता है बिना

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

+0

उलझन वाला नाम वैध सी पहचानकर्ता भी नहीं हो सकता है। – dan04

+0

सच है, लेकिन GetProcAddress (विंडोज़ डीएलएल) का उपयोग करके हम उलझन वाले नाम के साथ एक फ़ंक्शन को कॉल कर सकते हैं अगर हम जानते हैं कि उलझन वाला नाम क्या है। – arifwn

0

आप इस का उपयोग कर सकते:

class yourname 
{ 
    public: 
    ... 
    static void _cdecl AtExitCall(); 
}; 

int main() 
{ 
    ataexit(yourname::AtExitCall); 
} 
संबंधित मुद्दे