কীভাবে সুইফট থেকে সি কল করবেন?


136

সুইফট থেকে সি রুটিন কল করার কোনও উপায় আছে কি?

প্রচুর আইওএস / অ্যাপল লাইব্রেরি কেবল সি হয় এবং আমি এখনও তাদের কল করতে সক্ষম হতে চাই।

উদাহরণস্বরূপ, আমি সুইচ থেকে অবজেক্ট রানটাইম লাইব্রেরি কল করতে সক্ষম হতে চাই।

বিশেষত, আপনি আইওএস সি হেডারগুলি কীভাবে ব্রিজ করবেন?

উত্তর:


106

হ্যাঁ, আপনি অবশ্যই অ্যাপল সি লাইব্রেরিগুলির সাথে ইন্টারঅ্যাক্ট করতে পারেন। এখানে কিভাবে ব্যাখ্যা করা হয়।
মূলত, সি প্রকারসমূহ, সি পয়েন্টার ইত্যাদি সুইফট অবজেক্টে অনুবাদ করা হয়, উদাহরণস্বরূপ 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
আমি আইওএস / সুইফটে নতুন। আমি সুইফ্ট ফাইলগুলিতে # অন্তর্ভুক্ত <asl.h> থেকে লগিং সি-ফাংশনটি ব্যবহার করতে চাই। যে কেউ?
দিমিত্রি কোনোভালভ

এটি কি সি ++, .cpp ফাইলের সাথে সামঞ্জস্যপূর্ণ ??
কার্লোস.ভি

সরাসরি সি ++ ফাইলগুলি ব্যবহার করার জন্য আপনার উদ্দেশ্য-সি মোড়ক তৈরি করা উচিত। আপনি বাস্তবায়নটি (যা নিজেই একটি। মিমি ফাইলের মধ্যে থাকা উচিত) অবজেক্টিভ-সি ++ কোড (যা একটি ফাইলের মধ্যে কেবলমাত্র উদ্দেশ্য-সি এবং সি ++) রাখতে চান এবং ইন্টারফেসটি (যা তার নিজস্ব হওয়া উচিত should শিরোনাম ফাইল) খাঁটি অবজেক্টিভ-সি কোড থাকা উচিত, তাই আপনি সুইফটে এক্সপোজ করার জন্য সি ++ প্রকারগুলি বাস্তবায়নের ক্ষেত্রে অবজেক্টিভ সি ধরণের রূপান্তর করতে হবে। তারপরে আপনি সেই শিরোনামটি একটি উদ্দেশ্য-সি ব্রিজিং শিরোলেখ দিয়ে আমদানি করতে পারেন।
উইলিয়াম টি ফ্রোগার্ড

2
"আপনি অবশ্যই অ্যাপল সি লাইব্রেরিগুলির সাথে ইন্টারঅ্যাক্ট করতে পারেন" ভুল। আপনি যে কোনও সি লাইব্রেরির সাথে ইন্টারেক্ট করতে পারবেন , কেবলমাত্র অ্যাপলের সীমাবদ্ধ নয়।
স্লিপ ডি থম্পসন

আপডেট করা ডকুমেন্টেশন লিংক ডেভেলপার.এপল.
com/

9

সংকলকটি সি-পি-পি-কে স্যুইফটে রূপান্তরিত করে ঠিক যেমন এটি উদ্দেশ্য-সি এর জন্য করে।

import Cocoa

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

import Darwin

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

দস্তাবেজে অবজেক্টিভ-সি এপিআইয়ের সাথে ইন্টারঅ্যাক্টিং দেখুন ।


1
উদাহরণের জন্য ধন্যবাদ, এবং আপনি ঠিক বলেছেন, আমি কীভাবে এটি কাজ করতে পারে তা দেখতে পাচ্ছি। তবে এটি সত্যই আমার প্রশ্নের উত্তর দেয় না, এটি কীভাবে অ্যাপল সি লাইব্রেরি কল করতে হয়েছিল। তবে এটি অবশ্যই নিকটতম
জ্বলুন

সেই দস্তাবেজের অন্য কোথাও দেখুন। উদাহরণস্বরূপ, কোরফাউন্ডেশন-স্টাইলের "অবজেক্টস" ( CFTypeRef) সুইফ্ট অবজেক্টে রূপান্তরিত হয়েছে। যদিও বেশিরভাগ ObjCRuntime.h ফাংশন সুইফটের কাছে অর্থবহ নয়।
রিক্সার

"বেশিরভাগ ObjCRuntime.h ফাংশনগুলি সুইফ্টের পক্ষে অর্থপূর্ণ নয়, যদিও" আপনি কেন বলেন? আমি মনে করি আমাকে একটি শিরোনাম আমদানি করার এবং এটি ব্রিজ করার কোনও উপায় খুঁজে পাওয়া দরকার। এটি বিশ্রী মনে হয়, তবে আমি মনে করি এটি যাওয়ার উপায়।
জ্বলুন

5

আপনি যদি আমার মতো এক্সকোডে নতুন হন এবং লেয়ানড্রোর উত্তরে পোস্ট করা স্নিপেটগুলি চেষ্টা করতে চান তবে :

  1. File-> New-> প্রকল্প
  2. প্রকল্পের প্রিসেট হিসাবে কমান্ড লাইন সরঞ্জামটি চয়ন করুন এবং প্রকল্পটির নাম "ক্লিনপুট"
  3. প্রকল্প নেভিগেটরে ডান ক্লিক করুন (বাম দিকে নীল প্যানেল) এবং "নতুন ফাইল ..." চয়ন করুন
  4. ড্রপ ডাউন কথোপকথনে ফাইলটির নাম দিন "ইউজারইনপুট"। "একটি শিরোলেখ ফাইলও তৈরি করুন" বাক্সটি আনচেক করুন। একবার আপনি "পরবর্তী" ক্লিক করলে আপনাকে জিজ্ঞাসা করা হবে যে এক্সকোড আপনার জন্য ব্রিজিং-শিরোনাম h ফাইল তৈরি করে কিনা। "হ্যাঁ" চয়ন করুন।
  5. উপরের লিয়ানড্রোর উত্তর থেকে কোডটি অনুলিপি করুন এবং আটকান। একবার আপনি প্লে বাটনে ক্লিক করলে এটি টার্মিনালে সংকলন ও চালিত হওয়া উচিত, যা এক্সকোডে নীচের প্যানেলে অন্তর্নির্মিত। আপনি যদি টার্মিনালে একটি নম্বর প্রবেশ করান, একটি নম্বর ফিরে আসবে।

4

এই পোস্টটির ঝাঁকুনির মডিউল সমর্থন ব্যবহার করে কীভাবে করা যায় সে সম্পর্কেও একটি ভাল ব্যাখ্যা রয়েছে ।

এটি কমনক্রিপ্টো প্রকল্পের জন্য কীভাবে করা যায় সে ক্ষেত্রে এটি ফ্রেমযুক্ত, তবে সাধারণভাবে এটি সুইফটের মধ্যে থেকে অন্য যে কোনও সি লাইব্রেরিটি আপনি ব্যবহার করতে চান তার জন্য কাজ করা উচিত।

আমি 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()
    }
}

আপনি না আছে উপরে ক্ষেত্রে আমি সি ফাংশন হিসাবে একই func সুইফট বর্গ নামে ছাড়া, সামনে zlib লাইব্রেরি নাম করা, এবং যোগ্যতা থাকলে আপ সুইফট func প্রান্ত আবেদন স্থগিত না হওয়া পর্যন্ত বারবার বলা হচ্ছে।


3

সি ++ এর ক্ষেত্রে এই ত্রুটিটি পপ আপ হয়:

  "_getInput", referenced from: 

আপনার একটি সি ++ হেডার ফাইলও দরকার। আপনার ফাংশনে সি-লিঙ্কেজ যুক্ত করুন , তারপরে ব্রিজ-শিরোনামে শিরোলেখ ফাইলটি অন্তর্ভুক্ত করুন:

সুইফট 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
ক্রিস ইয়িম

1

পয়েন্টারগুলির সাথে কাজ করার সময় এটি একটি পৃথক বলের 'ও মোম' বলে মনে হয়। সি পসিক্স 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
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.