स्विफ्ट से सी कैसे कॉल करें?


136

क्या स्विफ्ट से सी रूटीन को कॉल करने का एक तरीका है?

बहुत सारे iOS / Apple लाइब्रेरी केवल C हैं और मैं अभी भी उन कॉल करने में सक्षम होना चाहूंगा।

उदाहरण के लिए, मैं objc रनटाइम पुस्तकालयों को तेजी से कॉल करने में सक्षम होना चाहता हूं।

विशेष रूप से, आप iOS C हेडर को कैसे पुल करते हैं?

जवाबों:


106

हां, आप निश्चित रूप से सेब सी लाइब्रेरी के साथ बातचीत कर सकते हैं। यहाँ बताया गया है कि कैसे।
मूल रूप से, C प्रकार, C पॉइंटर्स आदि का स्विफ्ट ऑब्जेक्ट में अनुवाद किया जाता है, उदाहरण के लिए C intमें स्विफ्ट एक है CInt

मैंने एक छोटे से उदाहरण का निर्माण किया है, एक और प्रश्न के लिए, जिसे थोड़ा स्पष्टीकरण के रूप में इस्तेमाल किया जा सकता है, सी और स्विफ्ट के बीच पुल कैसे करें:

main.swift

import Foundation

var output: CInt = 0
getInput(&output)

println(output)

UserInput.c

#include <stdio.h>

void getInput(int *output) {
    scanf("%i", output);
}

cliinput-ब्रिजिंग-Header.h

void getInput(int *output);

यहाँ मूल जवाब है।


1
मैं ios / स्विफ्ट के लिए नया हूं। मैं स्विफ्ट फ़ाइलों में #include <asl.h> से लॉगिंग सी-फंक्शन का उपयोग करना चाहूंगा। किसी को?
दिमित्री कोनोवलोव

यह सी ++, .cpp फ़ाइलों के साथ संगत है ??
कार्लोस .V

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

2
"आप निश्चित रूप से सेब सी पुस्तकालयों के साथ बातचीत कर सकते हैं" गलत। आप किसी भी C पुस्तकालयों के साथ बातचीत कर सकते हैं, केवल Apple तक सीमित सीमित नहीं।
स्लिप डी। थॉम्पसन

अपडेटेड डॉक्यूमेंटेशन लिंक developer.apple.com/documentation/swift/…
MechEthan

9

कंपाइलर सी एपीआई को स्विफ्ट में उसी तरह परिवर्तित करता है, जैसा वह ऑब्जेक्टिव-सी के लिए करता है।

import Cocoa

let frame = CGRect(x: 10, y: 10, width: 100, height: 100)

import Darwin

for _ in 1..10 {
    println(rand() % 100)
}

डॉक्स में ऑब्जेक्टिव-सी एपीआई के साथ सहभागिता देखें ।


1
उदाहरण के लिए धन्यवाद, और आप सही हैं, मैं देख सकता हूं कि यह कैसे काम कर सकता है। हालांकि यह वास्तव में मेरे सवाल का जवाब नहीं देता है, जो कि ऐप्पल सी लाइब्रेरीज़ को कॉल करना था। लेकिन यह निश्चित रूप से निकटतम है।
ब्लेज़

उस दस्तावेज़ में कहीं और देखें। उदाहरण के लिए, CoreFoundation-style "ऑब्जेक्ट्स" ( CFTypeRef) स्विफ्ट ऑब्जेक्ट्स में कनवर्ट किए जाते हैं। हालाँकि, अधिकांश ObjCRuntime.h फ़ंक्शन स्विफ्ट के लिए सार्थक नहीं हैं, हालाँकि।
रिकसर

"अधिकांश ObjCRuntime.h फ़ंक्शन स्विफ्ट के लिए सार्थक नहीं हैं, हालांकि" आप ऐसा क्यों कहते हैं? मुझे लगता है कि मुझे किसी हेडर को आयात करने और उसे पाटने के कुछ तरीके खोजने होंगे। यह अजीब लगता है, लेकिन मुझे लगता है कि यह जाने का रास्ता है।
ब्लेज़

5

बस के मामले में आप मेरे लिए XCode के रूप में नए हैं और Leandro के जवाब में पोस्ट किए गए स्निपेट्स आज़माना चाहते हैं :

  1. फ़ाइल> New-> परियोजना
  2. प्रोजेक्ट प्रीसेट के रूप में कमांड लाइन टूल चुनें और प्रोजेक्ट को "क्लिनपुट" नाम दें
  3. प्रोजेक्ट नेविगेटर (बाईं ओर नीला पैनल) पर राइट-क्लिक करें और "नई फ़ाइल ..." चुनें
  4. ड्रॉप डाउन डायलॉग में फ़ाइल का नाम "UserInput" है। बॉक्स को अनचेक करें "हेडर फ़ाइल भी बनाएं"। एक बार जब आप "अगला" पर क्लिक करते हैं, तो आपसे पूछा जाएगा कि क्या XCode आपके लिए Bridging-Header.h फ़ाइल बनाना चाहिए। "हाँ" चुनें।
  5. ऊपर दिए गए Leandro के उत्तर से कोड को कॉपी और पेस्ट करें। एक बार जब आप प्ले बटन पर क्लिक करते हैं तो इसे टर्मिनल में संकलित करना चाहिए और चलाना चाहिए, जो कि नीचे के पैनल में xcode में बनाया गया है। यदि आप टर्मिनल में एक नंबर दर्ज करते हैं, तो एक नंबर वापस आ जाएगा।

4

ये पद क्लैंग के मॉड्यूल समर्थन का उपयोग करने के बारे में एक अच्छी व्याख्या भी है ।

राष्ट्रमंडल परियोजना के लिए यह कैसे करना है, इसके संदर्भ में इसे तैयार किया गया है, लेकिन सामान्य तौर पर इसे किसी अन्य सी लाइब्रेरी के लिए काम करना चाहिए जिसे आप स्विफ्ट के भीतर से उपयोग करना चाहते हैं।

मैंने संक्षेप में ज़ालिब के लिए ऐसा करने का प्रयोग किया। मैंने एक नया iOS फ्रेमवर्क प्रोजेक्ट बनाया और एक डायरेक्टरी zlib बनाया, जिसमें निम्न के साथ एक मॉड्यूल। मोड्यूलमैप फ़ाइल थी:

module zlib [system] [extern_c] {
    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/zlib.h"
    export *
}

फिर लक्ष्य के तहत -> लिंक बाइनरी लाइब्रेरीज़ के साथ मैंने ऐड आइटम का चयन किया और libz.tbd को जोड़ा।

आप इस बिंदु पर निर्माण करना चाह सकते हैं।

मैं तब निम्नलिखित कोड लिखने में सक्षम था:

import zlib

public class Zlib {
    public class func zlibCompileFlags() -> UInt {
        return zlib.zlibCompileFlags()
    }
}

आपको zlib लाइब्रेरी नाम सामने रखने की आवश्यकता नहीं है , उपरोक्त मामले को छोड़कर मैंने स्विफ्ट क्लास का नाम C फ़ंक्शन के समान ही दिया गया है, और योग्यता के बिना स्विफ्ट की फ़ोकस को तब तक बार-बार कॉल किया जाता है जब तक कि आवेदन रुक नहीं जाता।


3

C ++ के मामले में, यह त्रुटि है कि पॉप अप:

  "_getInput", referenced from: 

आपको c ++ हैडर फ़ाइल भी चाहिए। अपने फ़ंक्शन में सी-लिंकेज जोड़ें , फिर ब्रिज-हेडर में हेडर फ़ाइल को शामिल करें:

स्विफ्ट 3

UserInput.h

#ifndef USERINPUT_H
#define USERINPUT_H    

#ifdef __cplusplus
extern "C"{
#endif

getInput(int *output);

#ifdef __cplusplus
}
#endif

UserInput.c

#include <stdio.h>

void getInput(int *output) {
    scanf("%i", output);
}    

main.swift

import Foundation
var output: CInt = 0
getInput(&output)
print(output)

cliinput-ब्रिजिंग-Header.h

#include "UserInput.h"

यहाँ मूल वीडियो यह समझा रहा है


यदि यह काम नहीं कर रहा है, __OBJCतो अपने ब्रिजिंग-हैडर में चेक जोड़ने का प्रयास करें, जैसे#ifdef __OBJC @import UIKit; #endif
क्रिस Yim

1

यह संकेत देने वालों के साथ काम करते समय एक अलग गेंद 'ओ मोम' प्रतीत होता है। यहाँ C COSIX readसिस्टम कॉल के लिए मेरे पास अब तक क्या है :

enum FileReadableStreamError : Error {
case failedOnRead
}

// Some help from: http://stackoverflow.com/questions/38983277/how-to-get-bytes-out-of-an-unsafemutablerawpointer
// and https://gist.github.com/kirsteins/6d6e96380db677169831
override func readBytes(size:UInt32) throws -> [UInt8]? {
    guard let unsafeMutableRawPointer = malloc(Int(size)) else {
        return nil
    }

    let numberBytesRead = read(fd, unsafeMutableRawPointer, Int(size))

    if numberBytesRead < 0 {
        free(unsafeMutableRawPointer)
        throw FileReadableStreamError.failedOnRead
    }

    if numberBytesRead == 0 {
        free(unsafeMutableRawPointer)
        return nil
    }

    let unsafeBufferPointer = UnsafeBufferPointer(start: unsafeMutableRawPointer.assumingMemoryBound(to: UInt8.self), count: numberBytesRead)

    let results = Array<UInt8>(unsafeBufferPointer)
    free(unsafeMutableRawPointer)

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