2009-06-29 18 views
5

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

#ifdef __cplusplus 
#import "cppheader.h" 
#endif 

@interface Foo : NSObject 
{ 
    id regularObjectiveCProperty; 
    #ifdef __cplusplus 
    CPPClass cppStuff; 
    #endif 
} 

@end 

यह काम करता है। कार्यान्वयन फ़ाइल में mm एक्सटेंशन है, ताकि इसे C++ के साथ मिश्रित उद्देश्य-सी के रूप में संकलित किया जा सके, #ifdef C++ सामान को अनलॉक करता है और वहां हम जाते हैं। जब कुछ अन्य, पूरी तरह से उद्देश्य-सी वर्ग हेडर आयात करता है, तो सी ++ सामान छिपा हुआ होता है और कक्षा को कुछ खास नहीं दिखता है। यह एक हैक की तरह दिखता है, क्या कोई बेहतर समाधान है?

+1

यह मूल रूप से मैं क्या जब मैं एक ही समस्या थी के साथ आए हैं क्या है:

और अधिक विस्तार और जानकारी के लिए आगे लिंक, एक पॉडकास्ट कि ObjC के बारे में ++ विस्तार से बात करती है सहित के लिए इस सूत्र देखें। लेकिन अपने ifdef पर ध्यान दें: आपको गैर-सीपीपी शाखा के लिए पैडिंग डालना होगा। अन्यथा कंपाइलर आपके फू ऑब्जेक्ट्स के आकार को नहीं जानता। हालांकि यह गैर-नाजुक उदाहरण var builds पर नहीं तोड़ सकता है, यह निश्चित रूप से पुरानी शैली के लक्ष्यों के लिए एक समस्या है। –

+0

मैंने ऊपर उल्लिखित दृष्टिकोण की प्रतिलिपि बनाई है। बहुत अच्छा और आसान माना जाता है, लेकिन फिर यह कुछ पागल स्मृति भ्रष्टाचार की समस्याओं का कारण बनता है: http://stackoverflow.com/questions/2458652/objective-c-insanity-simple-assignement-to-a-single-float-variable-results – morgancodes

उत्तर

8

यह एक इंटरफ़ेस/@ प्रोटोकॉल के लिए क्लासिक उपयोग की तरह लगता है। एपीआई के लिए एक उद्देश्य-सी प्रोटोकॉल परिभाषित करें और फिर अपने उद्देश्य-सी ++ वर्ग का उपयोग करके उस प्रोटोकॉल का कार्यान्वयन प्रदान करें। इस प्रकार ग्राहकों को केवल प्रोटोकॉल के बारे में पता होना चाहिए, न कि कार्यान्वयन के शीर्षलेख। तो मूल कार्यान्वयन

@interface Foo : NSObject 
{ 
    id regularObjectiveCProperty; 
    CPPClass cppStuff; 

} 

@end 

मैं

@interface Foo : NSObject <IFoo> 
{ 
    id regularObjectiveCProperty; 
    CPPClass cppStuff; 
} 

@end 

क्लाइंट कोड के लिए एक प्रोटोकॉल

//Extending the NSObject protocol gives the NSObject 
// protocol methods. If not all implementations are 
// descended from NSObject, skip this. 
@protocol IFoo <NSObject> 

// Foo methods here 
@end 

परिभाषित करेगा और संशोधित मूल Foo घोषणा तो प्रकार id<IFoo> के साथ काम कर सकते हैं और की जरूरत नहीं है को देखते हुए उद्देश्य-सी ++ के रूप में संकलित करने के लिए। जाहिर है आप इन ग्राहकों को Foo का उदाहरण दे सकते हैं।

+0

यदि @interface Foo .h फ़ाइल में है, तो यह obj-C++ को प्रभावित करने से रोकने के लिए संभव है? यदि @interface Foo .mm फ़ाइल में है, तो मैं इसका उदाहरण कैसे बना सकता हूं? – Eonil

+1

Foo.h आयात करने वाले किसी भी मॉड्यूल को उद्देश्य-सी ++ के रूप में संकलित करना होगा, लेकिन क्लाइंट कोड को IFoo का उपयोग करने के लिए * केवल * IFoo के शीर्षलेख की आवश्यकता होती है और इस प्रकार केवल उद्देश्य-सी हो सकती है। यह एक क्लासिक निर्भरता प्रबंधन पैटर्न है। आपके उदाहरण में –

+0

, हेडर आयात किए बिना एक नया Foo कैसे चालू करेगा? पहली बात जो दिमाग में आती है वह एक उद्देश्य सी ++ फैक्ट्री क्लास है जो आयात नहीं करती है और सी ++ अपने हेडर में सामान बनाती है। यह सब बहुत जटिल लगता है। यह दृष्टिकोण भी है: http://stackoverflow.com/questions/2262011/adding-c-object-to-objective-c-class/2262395 लेकिन मुझे इसे काम करने के लिए नहीं मिला है (देखें http://stackoverflow.com/प्रश्न/2463970/परेशानी-उपयोग-अपारदर्शी-पॉइंटर्स-इन-ऑब्जेक्ट-सी) – morgancodes

1

क्या कोई विशेष कारण है कि आप सब कुछ के लिए उद्देश्य सी ++ का उपयोग नहीं कर सकते हैं? बस कंपाइल स्रोतों को संकलित करने के लिए कंपाइलर स्विच करें: उद्देश्य सी ++ (या .cpp या .m से .mm तक अपनी सभी स्रोत फ़ाइलों का नाम बदलें)। तो फिर आप स्वतंत्र रूप से अपने सी ++ और उद्देश्य सी

सी ++ पूरे आवेदन

में फैल शुरू होता है मिश्रित कर सकते हैं क्या समस्या यह है कि के साथ है? यदि आपका उद्देश्य सी कोड सामान्य रूप से केवल सी/उद्देश्य सी कोड कर रहा है, तो यह लगभग निश्चित रूप से C++ के रूप में संकलित किए जाने पर प्रभावित नहीं होगा। कोई सराहनीय आकार या गति प्रदर्शन के मुद्दे नहीं हैं।

मुझे मिली केवल दो डाउनसाइड्स हैं: आप विश्लेषण (+) विश्लेषण के लिए क्लैंग स्थिर विश्लेषक का उपयोग नहीं कर सकते हैं; कुछ (अपेक्षाकृत अजीब) सी कोड सी ++ में काम नहीं करेगा, जो कभी-कभी तीसरे पक्ष सी कोड का उपयोग करते समय एक समस्या है।

+0

एकमात्र समस्या यह है कि मैं सी ++ के साथ सहज नहीं हूं और मुझे डर था कि कुछ सूक्ष्म अंतर होने जा रहे हैं बग का कारण बन सकता है। मुझे सी ++ के विचार को केवल कक्षा में encapsulated किया जाना चाहिए जो वास्तव में इसकी जरूरत है। लेकिन धन्यवाद, यह निश्चित रूप से एक समाधान है। – zoul

0

आपको लगता है कि आपको यह करने में समस्याएं हैं - मुझे ObjectiveC++ के बारे में क्या याद है, आपको पता चल सकता है कि आपके संलग्न सी ++ ऑब्जेक्ट के लिए कन्स्ट्रक्टर और विनाशक को कॉल नहीं किया जाएगा।

3

मैं हाल ही में इस मुद्दे में भी भाग गया। मेरे मामले में एक प्रोटोकॉल overkill था। मुझे केवल एक डेटा एक्सेस ऑब्जेक्ट में पॉइंटर रखने की आवश्यकता थी जो एक C++ ऑब्जेक्ट होता था।

मैंने जो किया वह कक्षा को void * इंस्टेंस वैरिएबल के साथ घोषित किया गया था और उदाहरण के तरीकों में इसका उपयोग करते समय इसे कास्ट किया गया था।

यह थोड़ा हैक-वाई है, लेकिन अवधारणात्मक रूप से, यह उद्देश्य-सी id प्रकार के समान ही है।

0

इस

ऐसा नहीं करते हैं तो आप एक उदाहरण चर, कि इस वर्ग के लिए दो अलग-अलग उदाहरण चर लेआउट दे देंगे बाहर ifdef। आपको जगह पर यादृच्छिक स्मृति स्मैशर्स मिलेंगे क्योंकि आधे मामलों में ऑब्जेक्ट के लिए आवंटित स्मृति बहुत कम होगी। उदाहरण चर बाहर ifdefing के बजाय, जैसे

struct CPPClass; 

अपने प्रकार आगे की घोषणा और इवर में इसे करने के लिए एक सूचक है, तो अपनी init/dealloc तरीकों नया फोन/वस्तु बनाने के लिए हटा दें। यदि आपके पास कई ऑब्जेक्ट्स हैं, तो आप सभी सी ++ इवार्स को सीधे पकड़ने के लिए एक स्ट्रक्चर बना सकते हैं और फिर उस स्ट्रक्चर को बस नया/हटा दें। Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?

+0

सी में, एक संरचना प्रकार को 'संरचना सीपीपी क्लास' के रूप में संदर्भित किया जाना चाहिए, न कि 'सीपीपी क्लास', इसलिए उन्हें भी इसे बदलना होगा। – newacct

+0

आईवर घोषणा में, हाँ, अच्छी पकड़। सी ++ स्ट्रक्चर फू और फू के समान हैं, इसलिए इसे केवल हेडर में ही जरूरी है। आम तौर पर मैं बस कक्षा के नाम के सामने संरचना लिखता हूं, जहां भी मैं इसका उपयोग करता हूं, आपको अलग-अलग संरचना घोषणा की आवश्यकता नहीं है जैसा मैंने यहां बताया है। – uliwitness

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