Wie rufe ich C von Swift aus an?

Lesezeit: 5 Minuten

Benutzeravatar von Blaze
Flammen

Gibt es eine Möglichkeit, C-Routinen von Swift aus aufzurufen?

Viele iOS / Apple-Bibliotheken sind nur C und ich würde diese immer noch gerne aufrufen können.

Zum Beispiel möchte ich die objc-Laufzeitbibliotheken von Swift aufrufen können.

Wie überbrücken Sie insbesondere iOS C-Header?

Benutzeravatar von Leandros
Leandros

Ja, Sie können natürlich mit den C-Bibliotheken von Apple interagieren. Hier wird erklärt wie.

Grundsätzlich werden die C-Typen, C-Zeiger usw. in Swift-Objekte übersetzt, beispielsweise ein C int in Swift ist a CInt.

Ich habe ein winziges Beispiel für eine andere Frage erstellt, die als kleine Erklärung verwendet werden kann, wie man eine Brücke zwischen C und Swift herstellt:

main.swift

import Foundation

var output: CInt = 0
getInput(&output)

println(output)

Benutzereingabe.c

#include <stdio.h>

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

cliinput-Bridging-Header.h

void getInput(int *output);

Hier ist die ursprüngliche Antwort.

  • Ich bin neu bei ios/swift. Ich möchte die Protokollierungs-C-Funktion von #include in Swift-Dateien verwenden. Jeder?

    – Dmitri Konovalov

    1. November 2014 um 0:30 Uhr


  • ist es kompatibel mit C++, .cpp-Dateien?

    – Carlos V

    12. November 2016 um 3:29 Uhr


  • Um C++-Dateien direkt zu verwenden, sollten Sie einen Objective-C-Wrapper erstellen. Sie möchten, dass die Implementierung (die sich selbst in einer .mm-Datei befinden sollte) Objective-C++-Code (der nur Objective-C und C++ in einer Datei enthält) und die Schnittstelle (die sich in einer eigenen .h-Datei befinden sollte) enthalten Header-Datei) sollte reinen Objective-C-Code enthalten, daher müssen Sie C++-Typen in der Implementierung in Objective-C-Typen konvertieren, um sie für Swift verfügbar zu machen. Dann können Sie diesen Header mit einem Objective-C-Bridging-Header importieren.

    – William T. Froggard

    6. Dezember 2016 um 1:23 Uhr


  • „Sie können natürlich mit Apples C-Bibliotheken interagieren“ Falsch. Sie können mit interagieren irgendein C-Bibliotheken, die überhaupt nicht auf Apples beschränkt sind.

    – Slipp D. Thompson

    20. März 2017 um 8:32 Uhr

  • Aktualisierter Dokumentationslink developer.apple.com/documentation/swift/…

    – MechaEthan

    11. Juni 2020 um 23:13 Uhr

Der Compiler konvertiert die C-API in Swift, genau wie bei Objective-C.

import Cocoa

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

import Darwin

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

Sehen Interaktion mit Objective-C-APIs in den Dokumenten.

  • Danke für das Beispiel, und du hast Recht, ich kann sehen, wie das funktionieren könnte. Es beantwortet jedoch nicht wirklich meine Frage, wie Apple C-Bibliotheken aufgerufen werden sollen. Aber es ist definitiv am nächsten.

    – Feuer

    2. Juni 2014 um 23:27 Uhr

  • Schauen Sie an anderer Stelle in diesem Dokument nach. Zum Beispiel “Objekte” im CoreFoundation-Stil (CFTypeRef) werden in Swift-Objekte konvertiert. Die meisten der ObjCRuntime.h-Funktionen sind für Swift jedoch nicht von Bedeutung.

    – Rickster

    2. Juni 2014 um 23:29 Uhr

  • “Die meisten Funktionen von ObjCRuntime.h sind für Swift jedoch nicht von Bedeutung.” Warum sagen Sie das? Ich denke, ich muss einen Weg finden, einen Header zu importieren und ihn zu überbrücken. Das scheint umständlich, aber ich denke, es ist der richtige Weg.

    – Feuer

    2. Juni 2014 um 23:34 Uhr

Benutzeravatar von lukas83
Lukas83

Nur für den Fall, dass Sie so neu bei XCode sind wie ich und die in Leandros Antwort geposteten Snippets ausprobieren möchten:

  1. Datei->Neu->Projekt
  2. Wählen Sie das Befehlszeilentool als Projektvoreinstellung und nennen Sie das Projekt “cliinput”.
  3. Klicken Sie mit der rechten Maustaste in den Projektnavigator (das blaue Feld auf der linken Seite) und wählen Sie “Neue Datei …”
  4. Benennen Sie im Dropdown-Dialog die Datei “UserInput”. Deaktivieren Sie das Kontrollkästchen “Auch eine Header-Datei erstellen”. Sobald Sie auf „Weiter“ klicken, werden Sie gefragt, ob XCode die Bridging-Header.h-Datei für Sie erstellen soll. Wählen Sie „Ja“.
  5. Kopieren Sie den Code aus Leandros Antwort oben und fügen Sie ihn ein. Sobald Sie auf die Wiedergabeschaltfläche klicken, sollte sie im Terminal kompiliert und ausgeführt werden, das in xcode im unteren Bereich integriert ist. Wenn Sie im Terminal eine Nummer eingeben, wird eine Nummer zurückgegeben.

Benutzeravatar von Julian
julianisch

Dieser Beitrag enthält auch eine gute Erklärung dazu, wie man dies mit Clangs macht Modulunterstützung.

Es ist darauf ausgelegt, wie dies für das CommonCrypto-Projekt zu tun ist, aber im Allgemeinen sollte es für jede andere C-Bibliothek funktionieren, die Sie in Swift verwenden möchten.

Ich habe kurz damit experimentiert, dies für zlib zu tun. Ich habe ein neues iOS-Framework-Projekt erstellt und ein Verzeichnis zlib erstellt, das eine module.modulemap-Datei mit Folgendem enthält:

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

Dann habe ich unter Targets -> Link Binary With Libraries die Option add items ausgewählt und libz.tbd hinzugefügt.

Vielleicht möchten Sie an dieser Stelle bauen.

Ich konnte dann folgenden Code schreiben:

import zlib

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

Du nicht haben um den Namen der zlib-Bibliothek voranzustellen, außer dass ich im obigen Fall die Swift-Klassenfunktion genauso benannt habe wie die C-Funktion, und ohne die Qualifikation wird die Swift-Funktion wiederholt aufgerufen, bis die Anwendung anhält.

Benutzeravatar von John James
John James

Im Fall von c++ gibt es diesen Fehler, der auftaucht:

  "_getInput", referenced from: 

Sie benötigen auch eine C++-Header-Datei. Fügen Sie Ihrer Funktion c-linkage hinzu und fügen Sie dann die Header-Datei in den Bridge-Header ein:

Schnell 3

UserInput.h

#ifndef USERINPUT_H
#define USERINPUT_H    

#ifdef __cplusplus
extern "C"{
#endif

getInput(int *output);

#ifdef __cplusplus
}
#endif

Benutzereingabe.c

#include <stdio.h>

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

main.swift

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

cliinput-Bridging-Header.h

#include "UserInput.h"

Hier ist das Original Video erklärt dies

  • Wenn es nicht funktioniert, versuchen Sie es hinzuzufügen __OBJC Überprüfen Sie Ihren Bridging-Header, z #ifdef __OBJC @import UIKit; #endif

    – Chris Yim

    31. August 2019 um 2:50 Uhr


Benutzeravatar von Chris Prince
Chris Prinz

Es scheint ein ganz anderer Ball ‘o Wax zu sein, wenn es um Pointer geht. Hier ist, was ich bisher zum Aufrufen des C POSIX habe read Systemaufruf:

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
}

  • Wenn es nicht funktioniert, versuchen Sie es hinzuzufügen __OBJC Überprüfen Sie Ihren Bridging-Header, z #ifdef __OBJC @import UIKit; #endif

    – Chris Yim

    31. August 2019 um 2:50 Uhr


1423960cookie-checkWie rufe ich C von Swift aus an?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy