2016-04-12 13 views
7

के तहत स्विफ्ट में इसका खुलासा करें क्या मूल सी या सी ++ कोड संकलित करने और लिनक्स पर स्विफ्ट करने का कोई तरीका है? मैं देख सकता हूं कि libdispatch जैसे कई ऐप्पल पुस्तकालय शुद्ध सी में लिखे गए हैं और आप उन्हें आयात करके स्विफ्ट में एक्सेस कर सकते हैं।संकलन सी कोड और लिनक्स

उदाहरण सेट करने के लिए मान लें कि मेरे पास दो फाइलें हैं Car.c और Car.h जो Car नाम की संरचना को परिभाषित करती हैं। क्या कोई तरीका है कि मैं उन्हें संकलित कर सकता हूं और आयात विवरण लिखकर स्विफ्ट में उनका उपयोग कर सकता हूं?

import Car 

मैं module.modulemap फ़ाइल निर्देशिका के अंदर जहां .c, .h और Package.swift फ़ाइलें स्थित हैं लेखन की कोशिश की है:

module Car { 
    header "Car.h" 
    export * 
} 

और swift build चल रहा है। यह उपज त्रुटि:

<unknown>:0: error: unexpected 'commands' value (expected map) 
<unknown>:0: error: unable to load build file 

मैं स्विफ्ट संस्करण 3.0-देव उपयोग कर रहा हूँ (24 मार्च 2016)

[अपडेट 1]

मैं से संपर्क किया है मैक्स (mxcl) - में से एक स्विफ्ट पैकेज मैनेजर के निर्माता और उन्होंने मुझे modulemap से छुटकारा पाने के लिए कहा और .c और .h फ़ाइलों को सीधे Sources फ़ोल्डर में डाला। मैंने पैकेज को संकलित करने के बाद यह मॉड्यूल के रूप में उपलब्ध नहीं है। इसके अलावा मैं .h फ़ाइल में किसी भी परिभाषित कार्यों को कॉल नहीं कर सकता।

+1

उद्देश्य-सी ब्रिजिंग या मॉड्यूल पर एक नज़र डालें। –

उत्तर

11

आप अपनी सी कोड के बाहर एक पुस्तकालय का निर्माण, तो आप एक बना सकते हैं इसके लिए सिस्टम मॉड्यूल, जिसे स्विफ्ट में आयात किया जा सकता है, यह उत्तर देखें: Use a C library in Swift on Linux

इस कार्य को देखने का एक और तरीका है ब्रिजिंग हेडर बनाना, जैसा कि @ फिलिप द्वारा सुझाया गया है। यहां एक oversimplified उदाहरण है। आइए निम्नलिखित सी कोड पर विचार करें:

/* In car.h */ 
int getInt(); 

/* In car.c */ 
int getInt() { return 123; } 

हम ब्रिजिंग हेडर के रूप में car.h का उपयोग करेंगे। तेज स्रोत (फ़ाइल junk.swift में) है:

print("Hi from swift!") 
var i = getInt() 
print("And here is an int from C: \(i)!") 

सबसे पहले, एक वस्तु फ़ाइल, car.o, car.c से बनाने के लिए:,

gcc -c car.c 

अब एक निष्पादन, junk निर्माण इस प्रकार है:

swiftc -import-objc-header car.h junk.swift car.o -o junk 

निष्पादन योग्य चलाना देता है:

$ ./junk 
Hi from swift! 
And here is an int from C: 123! 

-import-objc-header विकल्प छिपा हुआ है। यह और अन्य छिपा विकल्पों में से एक गुच्छा देखने के लिए, चलाएँ:

swiftc -help-hidden 

मैंने किया था इस का उपयोग करते हुए स्विफ्ट 3.0 विकास 12 अप्रैल से Ubuntu 14.04 के लिए स्नैपशॉट, यहाँ उपलब्ध है: https://swift.org/builds/development/ubuntu1404/swift-DEVELOPMENT-SNAPSHOT-2016-04-12-a/swift-DEVELOPMENT-SNAPSHOT-2016-04-12-a-ubuntu14.04.tar.gz

अब, आप उपयोग करना चाहते हैं सी ++, आपको एक सी ++ स्रोत फ़ाइल में लिखे गए एक रैपर बनाने की आवश्यकता होगी और सी ++ कंपाइलर के साथ संकलित किया जाएगा, लेकिन extern "C" का उपयोग कर सी से कॉल करने योग्य कार्यों के साथ। तब उन कार्यों को स्विफ्ट से किसी भी सी समारोह के रूप में बुलाया जा सकता है। देखें, उदाहरण के लिए, यह उत्तर: Can I mix Swift with C++? Like the Objective - C .mm files

+0

के लिए काम किया तो आप इस काम करने के लिए प्राप्त करने के लिए और सिर्फ 'आयात' बयान है कि के कारण को दूर कोशिश कर रहे हैं आप एक 'आयात' बयान पर एक "ऐसा कोई मॉड्यूल" त्रुटि हो रही है, तो त्रुटि। यह विधि आयात के साथ उपयोग के लिए एक स्विफ्ट मॉड्यूल नहीं बनाता है। इसके बजाय यह वैश्विक क्षेत्र में 'getInt()' जैसे कार्यों को बनाता है। – pauln

3

स्विफ्ट में सी कार्यों का उपयोग करने के लिए एक ब्रिजिंग हेडर की आवश्यकता होती है जिसमें आपको आवश्यक सभी सी कार्यक्षमता शामिल होती है। उदाहरण के लिए, myBridgingHeader.h जिसमें #include "Car.h" शामिल है और जो भी अन्य सी सामग्री आप चाहते हैं। मेरा मानना ​​है कि वर्तमान में सी ++ समर्थित नहीं है।

एक बार आपके पास ब्रिजिंग हेडर होने के बाद आपको इसके बारे में त्वरित जानकारी प्राप्त करने की आवश्यकता है। जब वे इसे परियोजना में जोड़ते हैं तो एक्सकोड उपयोगकर्ता इसे मुफ्त में प्राप्त करते हैं। लिनक्स में, संकलन करते समय '-import-objc-header/path/to/header' ध्वज का उपयोग करें।

संपादित करें: मैंने नीचे एक पूरा उदाहरण जोड़ा है जिसमें 6 अन्य फाइलें शामिल हैं जिनके पास यह प्रश्न हो सकता है। यह मूल रूप से ऊपर जैसा ही है, लेकिन मैंने यह नहीं देखा कि मैंने इसे पहले से ही हाहा रखा है। साथ ही, यह किसी ऐसे व्यक्ति के लिए उपयोगी हो सकता है जिसे स्थिर पुस्तकालयों के खिलाफ लिंक करने की आवश्यकता हो।

उचित रूप से नामित फ़ाइलों, make, ./hello पर फ़ाइल सामग्री की प्रतिलिपि बनाएँ और इसे काम करना चाहिए। रिकॉर्ड के लिए, मैं सिर्फ इस तेज संस्करण 2.2-देव पर (प्रयोग swift --version तुम्हारा जाँच करने के लिए) दौड़े हैं

  • hello.swift:

    let n: Int32 = 5 
    print("Hello, Swift World!") 
    print("mult2(\(n,N)) = \(mult2(n,N))") 
    print("CONST1=\(CONST1), CONST2=\(CONST2), CONST3=\(CONST3)") 
    
  • bridge.h:

    #include "defs.h" 
    #include "mult.h" 
    
  • defs.h:

    #define CONST1 1 
    #define CONST2 2 
    #define CONST3 3 
    
  • मल्टी।ज:

    #define N 7 
    int mult2(int,int); 
    
  • mult.c:

    #include "defs.h" 
    #include "mult.h" 
    int mult2(int a, int b) 
    { 
        return a*b; 
    } 
    
  • Makefile:

    all: hello 
    
    hello: libmult.a 
        swiftc hello.swift -import-objc-header ./bridge.h -L. -lmult -o hello 
    
    libmult.a: mult.o 
        ar -rc libmult.a mult.o 
        ranlib libmult.a 
    
    mult.o: mult.c mult.h defs.h 
        gcc -c mult.c -o mult.o 
    
    .PHONY: clean 
    clean: 
        rm -f *.o *.a hello 
    
+0

लिनक्स पर 'स्विफ्ट', न ही 'स्विफ्ट बिल्ड' कमांडों में '-import-objc-header' विकल्प (स्विफ्ट 3.0) –

+2

क्षमा करें, स्पष्ट होना चाहिए: आपको 'स्विफ्टसी' – Philip

+0

के साथ संकलित करना चाहिए, फिर भी, कोई 'आयात नहीं है -objc-header' विकल्प। –

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