क्या मैं स्विफ्ट को C ++ के साथ मिला सकता हूं? ऑब्जेक्टिव-सी .एमएम फाइलों की तरह


131

मैंने अभी अपनी .m फ़ाइलों को .mm और C ++ का उपयोग किया है। क्या स्विफ्ट के साथ भी ऐसा ही एक तरीका है?

जवाबों:


111

नहीं। जब आप .m से स्विच करते हैं। आप वास्तव में ऑब्जेक्टिव-सी से एक अलग भाषा (जिसमें कई सूक्ष्म अंतर होते हैं) पर स्विच कर रहे हैं, जिसे ऑब्जेक्टिव-सी ++ कहा जाता है। तो आप वास्तव में C ++ का उपयोग नहीं कर रहे हैं; आप Objective-C ++ का उपयोग कर रहे हैं, जो अधिकांश C ++ को इनपुट के रूप में स्वीकार करता है (उसी तरह जैसे कि C ++ सबसे अधिक नहीं, लेकिन सभी C को इनपुट के रूप में स्वीकार करता है)। जब मैं कहता हूं कि यह काफी C ++ नहीं है, तो C ++ फ़ाइल पर विचार करें जिसमें एक चर नाम है nil(जो कानूनी C ++ है) और फिर इसे Objective-C ++ के रूप में संकलित करने का प्रयास करें।

स्विफ्ट का समान संबंध नहीं है। यह C या C ++ का सुपरसेट नहीं है, और आप सीधे किसी .swiftफ़ाइल में उपयोग नहीं कर सकते ।

"स्विफ्ट विद कोको एंड ऑब्जेक्टिव-सी" का उपयोग भी हमें बताता है:

आप C ++ कोड को सीधे स्विफ्ट में आयात नहीं कर सकते। इसके बजाय, C ++ कोड के लिए एक उद्देश्य-सी या सी आवरण बनाएं।


93
वास्तव में बहुत कष्टप्रद - C / C ++ कोड बेस को शामिल करने वाले कोको ऐप के साथ हम सभी को अब 3 भाषाओं में लिखी परियोजनाओं को बनाए रखना होगा ....
Jay

6
मेरा सुझाव है कि ऑब्जेक्टिव-सी ++ एक अलग भाषा नहीं है, लेकिन सी ++ और ऑब्जेक्टिव-सी अंतर का मिश्रण सूक्ष्म है, लेकिन फिर भी वहाँ है
अमार

1
"Nil" कानूनी C ++ कैसे है? ऐसी कोई बात नहीं है (कम से कम मानक c ++ में) कृपया एक और उदाहरण प्रदान करें
rewolf

3
लेकिन ObjC के साथ आप बस .mmअपनी फ़ाइलों को जा सकते हैं और (लगभग) किया जा सकता है। स्विफ्ट के साथ ऐसा नहीं है।
चक्रित

6
@rewolf, मुझे लगता है कि उनका मतलब एक चर नाम है nil, जैसेint nil
ल्यूक

165

भ्रम की स्थिति इस धारणा से आ सकती है कि केवल से एक फ़ाइल एक्सटेंशन बदल .mकरने के लिए .mmआप सभी की, भाषाओं को पाटने के लिए जब, वास्तव में, यह है कि ऐसा कुछ नहीं करता है की जरूरत है। ऐसा नहीं है .mmकि .cppयह घर्षण का कारण बनता है , यह .hहेडर है जो सकारात्मक रूप से हेडर नहीं होना चाहिए C++


एक ही परियोजना: हाँ।

में एक ही परियोजना, आप खुशी से मिश्रण कर सकते हैं सी , सी ++ , ऑब्जेक्टिव-सी , उद्देश्य सी ++ , स्विफ्ट , और यहां तक कि विधानसभा

  1. ...Bridging-Header.h: आप इस पुल का उपयोग करके सी , ऑब्जेक्टिव-सी और ऑब्जेक्टिव-सी ++ को एक्सपोज करते हैं
  2. <ProductModuleName>-Swift.h: स्वचालित रूप से अपने स्विफ्ट कक्षाओं @objcको उद्देश्य-सी के साथ चिह्नित करता है
  3. .h: यह मुश्किल हिस्सा है, क्योंकि वे अस्पष्ट रूप से C , ++ या नहीं, उद्देश्य या नहीं के सभी स्वादों के लिए उपयोग किए जाते हैं । जब एक .hएकल C ++ कीवर्ड शामिल नहीं होता है , जैसे class, इसे जोड़ा जा सकता है ...Bridging-Header.h, और जो भी फ़ंक्शन .c या .cpp फ़ंक्शन इसे घोषित करता है, वह कार्य करेगा। अन्यथा, उस हेडर को या तो शुद्ध सी या ऑब्जेक्टिव-सी एपीआई में लपेटा जाना चाहिए ।

एक ही फाइल: नहीं।

एक ही फ़ाइल में, आप सभी को नहीं मिला सकते हैं। एक ही स्रोत फ़ाइल में :

  1. .swift: आप स्विफ्ट को कुछ भी नहीं मिला सकते हैं
  2. .m: आप मिश्रण कर सकते हैं ऑब्जेक्टिव-सी के साथ सी । ( @Vinzzz )
  3. .mm: आप C ++ के साथ ऑब्जेक्टिव-सी मिला सकते हैं । यह पुल ऑब्जेक्टिव-सी ++ है । ( @Vinzzz )।
  4. .c: शुद्ध सी
  5. .cpp: आप C ++ और असेंबली ( @Vality ) को मिला सकते हैं
  6. .h: सर्वव्यापी और अस्पष्ट C , C ++ , Objective-C या Objective-C ++ , इसलिए इसका उत्तर यह निर्भर करता है।

संदर्भ


1
सुधार: एक ही .m स्रोत फ़ाइल में, ऑब्जेक्टिव-सी एक सख्त C सुपरसेट है, आप Object-C और C को मिला सकते हैं ...
Vinzzz

1
कोई बात नहीं, मैं क्रेडिट की परवाह भी नहीं करता, जब तक कि उत्तर सही एक है?) BTW, .mm , ऑब्जेक्टिव-सी और C ++ को मिलाने के लिए है (C और C ++ दो अलग-अलग चीजें हैं, नाम के बावजूद। )
विनज़्ज़ सिप १

1
मैं उल्लेख करूंगा कि उद्देश्य C के विपरीत, C ++ एक C सुपरसेट नहीं है, इसलिए आप एक cpp फ़ाइल में C और C ++ दोनों को नहीं मिला सकते हैं। केवल C ++ और असेंबली।
10

1
मामले में किसी को भी यह पता चलता है कि स्विफ्ट फ़ाइलों को उनके ऑब्जेक्टिव-सी / सी ++ फाइल में एक्सपोज करने का प्रयास करने पर यह विस्तृत उत्तर काफी मदद नहीं करता है (Xcode शिकायत कर रहा है कि स्विफ्ट हेडर फाइल नहीं मिली है)। मैंने पाया कि मुझे अपने Objective-C / C ++ सोर्स फाइल में "ProductName / ProductModuleName-Swift.h" इंपोर्ट करना था । मैंने इसे कुछ हद तक दफन कर दिया: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
AeroBuffalo

अच्छी बात। इन भाषाओं को मिलाने वाले एक कार्यशील प्रोजेक्ट के लिए, stackoverflow.com/a/32546879/218152 पर एक नज़र डालें ।
स्विफ्टआर्किटेक्ट

72

मैंने एक सरल Xcode 6 प्रोजेक्ट लिखा, जिसमें C ++, ऑब्जेक्टिव C और स्विफ्ट कोड को मिक्स करने का तरीका दिखाया गया है:

https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console

विशेष रूप से उदाहरण स्विफ्ट से एक उद्देश्य सी और एक सी ++ फ़ंक्शन को कॉल करता है।

कुंजी एक साझा हेडर प्रोजेक्ट-ब्रिजिंग-हेडर बनाने के लिए है और वहां उद्देश्य सी हेडर डालते हैं।

कृपया प्रोजेक्ट को पूर्ण उदाहरण के रूप में डाउनलोड करें।


इस जियान के लिए धन्यवाद!
जेसन एलवुड

इस उदाहरण के लिए धन्यवाद, लेकिन अगर मैं ObjCtoCPlusPlus.mm फ़ाइल से #import "CPlusPlus.h" को ObjCtoCPlusPlus.h फ़ाइल में ले जाना चाहता हूं, तो कंपाइलर इस त्रुटि को लौटाएं: 'अज्ञात:: 0: त्रुटि: ब्रिजिंग हेडर आयात करने में विफल'। /Users/Ale/Downloads/sared-master/C-ObjC-Swift/Performance_Console/Performance_Console/Performance_Console-Bridging-Header.h 'क्या यह संभव है हैडर फ़ाइल में इस कदम को स्थानांतरित करने के लिए?
एलेसेंड्रो पिरोवानो

@API: नहींं, आपको बात याद आ रही है। ObjCtoCPlusPlus.h/ `` .mm` C ++ कोड को Ob-C इंटरफ़ेस प्रदान करने के एकमात्र उद्देश्य के लिए मौजूद है- यह पुल है, जो यहां एक आवश्यक घटक है। जहां वे हैं, वहां शामिल करें और ObjCtoCPlusPlus.…प्रत्येक C ++ विधि के लिए फ़ाइलों में एक विधि जोड़ें, जिनकी आपको आवश्यकता है। आप sourcemaking.com/design_patterns/adapter
स्लिप डी। थॉम्पसन

मैंने आपका उदाहरण डाउनलोड किया और यह STATIC फ़ंक्शन के लिए एक उदाहरण के रूप में प्रदान की गई कक्षा के लिए शानदार है, लेकिन मैं बाहर से उपयोग किए जाने वाले अतिरिक्त गैर-स्थिर फ़ंक्शन के लिए उदाहरण को अनुकूलित करने का प्रबंधन नहीं कर सकता ... क्या यह भी संभव है? (मैंने अपना सी ++ होमवर्क दशकों पहले किया था ... मैं अभी बॉक्स की सबसे तेज पेंसिल नहीं हूँ)
इसहाक

31

आप बीच - बीच में ऑब्जेक्टिव-सी फाइल को भी छोड़ सकते हैं । बस .cpp स्रोत फ़ाइल के साथ C हेडर फ़ाइल जोड़ें। हेडर फ़ाइल में केवल C घोषणाएँ हैं और स्रोत फ़ाइल में कोई C ++ कोड शामिल करें। फिर सी हेडर फ़ाइल को ** - ब्रिजिंग-हेडर.ह में शामिल करें।

निम्न उदाहरण एक C ++ ऑब्जेक्ट (स्ट्रक्चर फू) के लिए एक पॉइंटर लौटाता है, इसलिए स्विफ्ट वैश्विक फ़ू में परिभाषित किए गए स्ट्रक्चर फू को परिभाषित करने के बजाय एक COpaquePointer में स्टोर कर सकता है।

Foo.h फ़ाइल (स्विफ्ट द्वारा देखी गई - ब्रिजिंग फ़ाइल में शामिल)

#ifndef FOO_H
#define FOO_H

// Strictly C code here.
// 'struct Foo' is opaque (the compiler has no info about it except that 
// it's a struct we store addresses (pointers) to it.
struct Foo* foo_create();
void foo_destroy(struct Foo* foo);

#endif

अंदर स्रोत फ़ाइल Foo.cpp (स्विफ्ट द्वारा नहीं देखी गई):

extern "C"
{
#include "Foo.h"
}
#include <vector>

using namespace std;

// C++ code is fine here. Can add methods, constructors, destructors, C++ data members, etc.
struct Foo
{
   vector<int> data;
};

struct Foo* foo_create()
{
   return new Foo;
}

void foo_destroy(struct Foo* foo)
{
    delete foo;
}

1
इस उत्तर के हकदार रास्ता अधिक upvotes। वास्तव में उपयोगी।
rsp1984

यह पहली बार है जब मैंने extern "C"हेडर को उस जगह पर लपेटा है जहाँ वह #ifdefहेडर फ़ाइल में एड के बजाय शामिल है। प्रतिभाशाली!
dcow

27

मैंने सिर्फ स्विफ्ट, ऑब्जेक्टिव-सी और सी ++ का उपयोग करके एक छोटा सा उदाहरण प्रोजेक्ट बनाया है। यह iOS में OpenCV सिलाई का उपयोग करने का एक डेमो है। OpenCV एपीआई C ++ है इसलिए हम स्विफ्ट से सीधे इस पर बात नहीं कर सकते हैं। मैं एक छोटे रैपर वर्ग का उपयोग करता हूं, जिसका कार्यान्वयन फ़ाइल ऑब्जेक्टिव-सी ++ है। हैडर तो स्विफ्ट सीधे इस बात कर सकते हैं फ़ाइल, स्वच्छ ऑब्जेक्टिव-सी है। आपको ध्यान रखना है कि किसी भी C ++ - ish फ़ाइलों को अप्रत्यक्ष रूप से आयात न करें जो कि हेडर में है जो स्विफ्ट के साथ इंटरैक्ट करता है।

परियोजना यहां है: https://github.com/foundry/OpenCVSwiftStitch


मुझे लगता है कि यह एक ऐसी समस्या का जवाब देता है जो मैंने आज मारा है कि स्विफ्ट के साथ 3 जी लाइब्रेरी लाइब्रेरी कुडनकवी का उपयोग करने की कोशिश की जा रही है। मेरा ब्रिजिंग हेडर उनकी .h फ़ाइल को आयात करता है जिसमें <मेमोरी> <स्ट्रिंग्स> और <वैक्टर> का आयात होता है, जो मुझे लगता है कि C ++ लाइब्रेरी या फ़ाइलों से हैं, नतीजतन मेरा स्विफ्ट कोड संकलित नहीं होगा। मैं आभारी हूँ अगर कोई मुझे बता सकता है कि क्या कोई रास्ता है इसके आसपास ... या अगर मुझे अपने सभी कोड को फिर से लिखना है ऑब्जेक्टिव-सी
रॉकेट गार्डन

1
@RocketGarden - KudanCV हेडर फ़ाइल C ++ है। आप एक रैपर लिख सकते हैं जो मेरे उदाहरण के आवरण वर्ग के समान काम करता है। या आप अपने ऐप के उन हिस्सों को फिर से लिखते हैं, जिन्हें वस्तुनिष्ठ-सी ++ (ऑब्जेक्टिव-सी हेडर के साथ) में कुंदनकवी से बात करने की जरूरत है। आपको अपनी परियोजना के उन हिस्सों को फिर से लिखने की ज़रूरत नहीं होगी जो कुडनकवीवी से चिंतित नहीं हैं।
फाउंड्री

इसके लिए धन्यवाद, मैंने इसे लगभग 5 मिनट बाद महसूस किया, लेकिन दूसरों के लिए इसे रिकॉर्ड करने के लिए उपयोगी है।
रॉकेट गार्डन

13

यहां C ++ / स्विफ्ट संचार को स्वचालित करने के लिए एक क्लैंग टूल पर मेरा प्रयास है। आप C ++ क्लासेस को स्विफ्ट से, C ++ क्लास से इनहेरिट कर सकते हैं और यहां तक ​​कि स्विफ्ट में वर्चुअल तरीके भी ओवरराइड कर सकते हैं।
यह C ++ वर्ग को पार्स करेगा जिसे आप अपने आप ही Objective-C / Objective-C ++ ब्रिज को स्विफ्ट और जेनरेट करने के लिए एक्सपोर्ट करना चाहते हैं।

https://github.com/sandym/swiftpp


8

स्विफ्ट सी ++ के साथ सीधे संगत नहीं है। आप अपने C ++ कोड को ऑब्जेक्टिव-C के साथ लपेटकर, और स्विफ्ट में ऑब्जेक्टिव C रैपर का उपयोग करके समस्या का समाधान कर सकते हैं।


यह जो मैंने किया है। मैंने सी + + को एक स्विफ्ट प्रोजेक्ट के साथ एकीकृत करने के तरीके पर एक लेख लिखा: learningswift.brightdigit.com/integrating-c-plus-plus-swift
leogdion


4

नहीं, एक भी फाइल में नहीं।

हालांकि, आप स्विफ्ट प्रोजेक्ट्स में C ++ का उपयोग स्टैटिक लाइब्रेरी या फ्रेमवर्क की आवश्यकता के बिना कर सकते हैं। जैसा कि अन्य लोगों ने कहा है, कुंजी एक ऑब्जेक्टिव-सी ब्रिजिंग हेडर बनाने के लिए है जो सी-संगत C ++ हेडर को #includes करता है जिसे एक्सटर्नल "C" {} ट्रिक के साथ C संगत के रूप में चिह्नित किया गया है ।

वीडियो ट्यूटोरियल: https://www.youtube.com/watch?v=0x6JbiphNS4


2

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

यह फ़ाइल (c.swift) एक मान्य निष्पादन योग्य दोनों के साथ संकलित करती है swiftc c.swiftऔरclang -x objective-c c.swift

/* /* */
#if 0
// */
import Foundation
print("Hello from Swift!")
/* /* */
#endif
#include <stdio.h>
int main()
{
    puts("Hello from C!");
    return 0;
}
// */

आपका नमूना कोड C नहीं C ++ में है। बेहतर <iostream> उदाहरण IMHO के साथ जाएं।
kakyo

2

एक चाल (कई की) है

आपको अपने ब्रिजिंग obj-c ++ फ़ाइल के लिए एक अलग हेडर चाहिए ...

आप केवल। में और @ फ़ाइल को एक ही .mm फ़ाइल में नहीं फेंक सकते हैं क्योंकि एक सामान्य रूप से अक्सर होता है।

तो आपके ब्रिजिंग हेडर फ़ाइल में आपके पास है

#import "Linkage.hpp"

Linkage.hpp में लिंकेज के लिए @interface और Linkage.mm के पास .mm के लिए @ कार्यान्वयन है

और तब

... आप वास्तव में Linkage.hpp में "yourCpp.hpp" #include न करें

आप केवल #include "yourCpp.hpp"लिंकेज.एमएम फाइल में लगाएं, लिंकेज.एचपी फाइल में नहीं

कई ऑनलाइन उदाहरणों / ट्यूटोरियल्स में, लेखक केवल .mm फ़ाइल में @interface और @ कार्यान्वयन लागू करता है, जैसा कि अक्सर होता है।

यह बहुत ही सरल cpp ब्रिजिंग उदाहरणों में काम करेगा, लेकिन,

यह समस्या है:

यदि आपके cpp.hpp में कोई भी c ++ विशेषताएँ हैं, जो निश्चित रूप से यह (जैसे, पहली पंक्ति #include <something>) होगी, तो प्रक्रिया विफल हो जाएगी।

लेकिन अगर आप नहीं करते है #include "yourCpp.hpp"लिंकेज में हैडर फ़ाइल (यह ठीक .mm फ़ाइल में है, स्पष्ट रूप से आप की आवश्यकता होगी) - यह काम करता है।

फिर से यह दुर्भाग्य से पूरी प्रक्रिया में सिर्फ एक टिप है।


1

यदि यह किसी के लिए उपयोगी है, तो मेरे पास एक सामान्य सी ++ स्टेटिक लाइब्रेरी को एक तुच्छ स्विफ्ट कमांड लाइन उपयोगिता से कॉल करने पर एक संक्षिप्त ट्यूटोरियल है। यह कोड के कॉन्सेप्ट पीस का वास्तव में नंगे-हड्डियों का प्रमाण है।

कोई उद्देश्य-सी शामिल नहीं है, बस स्विफ्ट और सी ++। C ++ लाइब्रेरी में कोड को C ++ रैपर द्वारा कहा जाता है जो एक्सटर्नल "C" लिंकेज के साथ एक फंक्शन को कार्यान्वित करता है। उस फ़ंक्शन को ब्रिजिंग हेडर में संदर्भित किया जाता है और स्विफ्ट से बुलाया जाता है।

Http://www.swiftprogrammer.info/swift_call_cpp.html देखें


1

मैं आधिकारिक संसाधन में SE-0038 का लिंक प्रदान कर रहा हूं , जैसा कि यह बताया गया है कि यह स्विफ्ट प्रोग्रामिंग लैंग्वेज में बदलाव और उपयोगकर्ता-दृश्यमान संवर्द्धन के प्रस्तावों को बनाए रखता है।

आज की स्थिति यह है कि यह सुविधा अनुरोध है जिसे स्वीकार किया गया है लेकिन अभी तक निर्धारित नहीं है।

यह लिंक सही दिशा में इस सुविधा की तलाश में किसी को भी चलाने का इरादा है

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