C कोड में C ++ लाइब्रेरी का उपयोग करना


103

मेरे पास C ++ लाइब्रेरी है जो डेटा के प्रबंधन के लिए विभिन्न कक्षाएं प्रदान करती है। मेरे पास पुस्तकालय के लिए स्रोत कोड है।

मैं C फ़ंक्शन कॉल का समर्थन करने के लिए C ++ API का विस्तार करना चाहता हूं ताकि लाइब्रेरी का उपयोग C कोड और C ++ कोड के साथ एक ही समय में किया जा सके।

मैं GNU टूल चेन (gcc, glibc, आदि) का उपयोग कर रहा हूं, इसलिए भाषा और आर्किटेक्चर समर्थन कोई समस्या नहीं है।

क्या कोई कारण है कि यह तकनीकी रूप से संभव नहीं है?

क्या कोई गोटा है जिसे मुझे देखने की आवश्यकता है?

क्या इस बारे में संसाधन, उदाहरण कोड और / या दस्तावेज उपलब्ध हैं?


कुछ और बातें जो मुझे पता चली हैं:

  1. अपने C ++ हेडर को लपेटने के लिए निम्नलिखित का उपयोग करें जिन्हें C कोड द्वारा उपयोग करने की आवश्यकता है।

#ifdef __cplusplus
extern "C" {  
#endif  
//  
// Code goes here ...  
//  
#ifdef __cplusplus  
} // extern "C"  
#endif
  1. सी। थिंक PIMPL सिद्धांत द्वारा शामिल नहीं किए गए अलग हेडर फ़ाइलों में "वास्तविक" C ++ इंटरफेस रखें । #ifndef __cplusplus #errorसामान का उपयोग करने से यहां किसी भी पागलपन का पता लगाने में मदद मिलती है।
  2. सी कोड में नाम के रूप में सी ++ पहचानकर्ताओं से सावधान
  3. C और C ++ कंपाइलर के बीच आकार में भिन्नता। यदि आप GNU टूल चेन का उपयोग कर रहे हैं, तो संभवतः कोई समस्या नहीं है, लेकिन फिर भी, सावधान रहें।
  4. संरचना के लिए निम्नलिखित फ़ॉर्म का पालन करें ताकि सी भ्रमित न हो।

    typedef struct X { ... } X
  5. फिर C ++ ऑब्जेक्ट्स के आस-पास से गुजरने के लिए पॉइंटर्स का उपयोग करें, उन्हें बस C को स्ट्रक्चर X के रूप में घोषित करना होगा जहां X C ++ ऑब्जेक्ट है।

यह सब एक मित्र का शिष्टाचार है जो C ++ में एक जादूगर है।


5
: कुछ हद तक देर हो चुकी है, लेकिन मैं एक छोटे से howto सी ++ के लिए सी आवरण के बारे में लिखा teddy.ch/c++_library_in_c
टेडी

जवाबों:


69

हां, यह निश्चित रूप से संभव है। आपको C ++ में एक इंटरफ़ेस लेयर लिखने की आवश्यकता होगी जो इसके साथ फ़ंक्शन की घोषणा करती है extern "C":

extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}

फिर, आप foo()अपने C मॉड्यूल से कॉल करेंगे , जो realFoo()C ++ में लागू होने वाले फ़ंक्शन को कॉल पास करेगा ।

यदि आपको डेटा सदस्यों और विधियों के साथ एक पूर्ण C ++ वर्ग को उजागर करने की आवश्यकता है, तो आपको इस सरल फ़ंक्शन उदाहरण से अधिक काम करने की आवश्यकता हो सकती है।


extern "C"केवल घोषणाओं में रखा जाना चाहिए (और परिभाषाओं में नहीं)? क्योंकि आपने "परत जो फ़ंक्शन घोषित करता है" का उल्लेख किया है, लेकिन आपका नमूना कोड भी एक परिभाषा है। दूसरे शब्दों में, क्या हमें इसे हेडर फ़ाइलों या स्रोत फ़ाइलों में रखना चाहिए? (या दोनों?)
kyriakosSt

@ कीर्स्ट: यदि आपके पास फ़ंक्शन घोषणा के साथ एक हेडर फ़ाइल है, तो आपको कम से कम extern "C"वहां रखना होगा। आपका कंपाइलर आपको बताएगा कि क्या आपको इसे परिभाषा पर रखना है।
ग्रेग हेविल

23

C ++ FAQ Lite: "C और C ++ कोड को कैसे मिक्स करें"

इन प्रश्नों के उत्तर में कुछ गोत्रों का वर्णन किया गया है:

  • [३२. [] मैं एक C फ़ंक्शन से C ++ क्लास के ऑब्जेक्ट को कैसे पास कर सकता / सकती हूं?
  • [३२.९] क्या मेरा C एक C ++ क्लास के ऑब्जेक्ट में सीधे डेटा एक्सेस कर सकता है?

12

मुख्य गोटचा: अपवादों को सी में नहीं पकड़ा जा सकता है। यदि सी ++ कोड में अपवाद बढ़ने की संभावना है, तो या तो अपना सी कोड या अपने सी ++ रैपर्स को बहुत सावधानी से लिखें। इसके विपरीत, सी कोड में तंत्र (जैसे, लॉन्गंप) के अपवाद (जैसा कि विभिन्न स्क्रिप्टिंग भाषाओं में पाया जाता है) को स्टैक पर सी ++ ऑब्जेक्ट्स के लिए विनाशकों को आमंत्रित करने की आवश्यकता नहीं होती है।


2
Longjump कॉल के बारे में शानदार बात। जबकि मैं उन्हें सीधे उपयोग नहीं करता, परीक्षण फ्रेमवर्क जो मैं उपयोग करता हूं, उन्हें लागू करते हैं। मन में कुछ रखने के लिए। साभार
मिशा एम

3

आप C / C ++ कोड मिला सकते हैं। यदि आपका मुख्य () C ++ में कार्य करता है, तो आपको केवल यह सुनिश्चित करने की आवश्यकता है कि आपके सी फ़ंक्शन घोषित हैं

extern "C"

यदि आपका मुख्य C है, तो आप शायद स्थिर चर को छोड़कर ठीक हैं। आपके स्थिर चर वाले किसी भी निर्माणकर्ता को मुख्य () शुरू होने से पहले बुलाया जाना चाहिए। यदि C आपका मुख्य है तो यह नहीं होगा। मेरे पास बहुत सारे स्टैटिक वैरिएबल हैं, सबसे अच्छी बात यह है कि स्टैटिक वेरिएबल्स को सिंग्लेटन्स से बदलना है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.