wake-up-neo.com

Kann ich Swift mit C ++ mischen? Wie die Objective-C .mm-Dateien

Ich habe gerade meine .m-Dateien in .mm geändert und benutze C++. Gibt es eine Möglichkeit, mit Swift dasselbe zu tun?

126
EhTd

Nein. Wenn Sie von .m zu .mm wechseln, wechseln Sie tatsächlich von Objective-C zu einer anderen Sprache (die viele subtile Unterschiede aufweist), die als Objective-C++ bezeichnet wird. Sie verwenden also nicht wirklich C++. Sie verwenden Objective-C++, das die meisten C++ als Eingabe akzeptiert (genauso wie C++ die meisten, aber nicht alle C als Eingabe akzeptiert). Wenn ich sage, dass es nicht ganz C++ ist, betrachten Sie eine C++ - Datei, die eine Variable mit dem Namen nil enthält (was für C++ zulässig ist), und versuchen Sie dann, diese als Objective-C++ zu kompilieren.

Swift hat nicht die gleiche Beziehung. Es ist keine Obermenge von C oder C++, und Sie können auch nicht direkt in einem .Swift Datei.

"Verwenden von Swift mit Cocoa und Objective-C" sagt uns auch:

Sie können C++ - Code nicht direkt in Swift importieren. Erstellen Sie stattdessen einen Objective-C- oder C-Wrapper für C++ - Code.

109
Rob Napier

Die Verwirrung kann von der Annahme herrühren, dass das bloße Ändern einer Dateierweiterung von .m in .mm alles ist, was Sie zum Überbrücken der Sprachen benötigen, wenn dies in Wirklichkeit nicht der Fall ist. Es ist nicht der .mm, der Reibung mit .cpp verursacht, sondern der .h -Header, der eindeutig kein C++ -Header sein darf.


Gleiches Projekt: Ja.

Im Projekt same können Sie C , C++, Objective-C, Objective C++, Swift ​​und sogar Assembly.

  1. ...Bridging-Header.h: Sie legen C , Objective-C und Objective-C++ offen um Swift ​​mit dieser Brücke
  2. <ProductModuleName>-Swift.h: macht automatisch Ihre Swift ​​Klassen, die mit @objc bis Objective-C markiert sind
  3. .h: Dies ist der schwierige Teil, da sie mehrdeutig für alle Geschmacksrichtungen von C , ++ verwendet werden = oder nicht Ziel oder nicht. Wenn ein .h kein einzelnes C++ - Schlüsselwort enthält, wie z. B. class, kann es zum ...Bridging-Header.h hinzugefügt werden und macht alles verfügbar Funktionieren Sie die entsprechenden .coder.cpp deklarierten Funktionen. Andernfalls muss dieser Header in eine reine C - oder Objective-C -API eingeschlossen werden.

Gleiche Datei: Nein.

In der same -Datei können nicht alle 5 gemischt werden. In derselben Quelldatei:

  1. .Swift: Sie können nicht mischen Swift ​​mit irgendetwas
  2. .m: Sie können Objective-C mit C mischen. ( @ Vinzzz )
  3. .mm: Sie können Objective-C mit C++ mischen. Diese Brücke ist Objective-C++. ( @ Vinzzz ).
  4. .c: pure C
  5. .cpp: Sie können mischen C++ & Assembly ( @ Vality )
  6. .h: ubiquitär und mehrdeutig C , C++, Objective-C oder Objective-C++, also lautet die Antwort es kommt darauf an.

Referenzen

159
SwiftArchitect

Ich habe ein einfaches Xcode 6-Projekt geschrieben, das zeigt, wie man C++, Objective C und Swift code mischt:

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

Insbesondere ruft das Beispiel eine Objective C- und eine C++ - Funktion von der Swift auf.

Der Schlüssel besteht darin, einen gemeinsam genutzten Header "Project-Bridging-Header.h" zu erstellen und die Objective C-Header dort abzulegen.

Bitte laden Sie das Projekt als vollständiges Beispiel herunter.

72

Ich habe gerade ein kleines Beispielprojekt mit Swift, Objective-C und C++ erstellt. Es ist eine Demo zur Verwendung von OpenCV-Stitching unter iOS. Die OpenCV-API ist C++, daher können wir nicht direkt von Swift aus mit ihr sprechen. Ich verwende eine kleine Wrapper-Klasse, deren Implementierungsdatei Objective-C++ ist. Die Header Datei ist sauber Objective-C, also kann Swift direkt mit dieser reden. Sie müssen nicht aufpassen zum indirekten Importieren von C++ - Dateien in die Header, mit denen Swift interagiert.

Das Projekt ist hier: https://github.com/foundry/OpenCVSwiftStitch

27
foundry

Sie können auch überspringen Sie die Objective-C Datei dazwischen. Fügen Sie einfach eine C-Header-Datei mit einer CPP-Quelldatei hinzu. Enthält nur C-Deklarationen in der Headerdatei und enthält C++ - Code in der Quelldatei. Fügen Sie dann die C-Header-Datei in die Datei ** - Bridging-Header.h ein.

Das folgende Beispiel gibt einen Zeiger auf ein C++ - Objekt (struct Foo) zurück, sodass Swift in einem COpaquePointer gespeichert werden kann, anstatt struct Foo im globalen Raum zu definieren.

Foo.h Datei (gesehen von Swift - enthalten in der Überbrückungsdatei)

#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

Innerhalb der Quelldatei Foo.cpp (von Swift nicht gesehen):

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;
}
25
Dan G

Hier ist mein Versuch, mit einem Clang-Tool die C++/Swift-Kommunikation zu automatisieren. Sie können C++ - Klassen von Swift instanziieren, von C++ - Klassen erben und sogar virtuelle Methoden in Swift überschreiben.
Es analysiert die C++ - Klasse, die Sie nach Swift exportieren möchten, und generiert die Objective-C/Objective-C++ - Brücke automatisch.

https://github.com/sandym/swiftpp

13
Sandy

Swift ist nicht direkt mit C++ kompatibel. Sie können das Problem umgehen, indem Sie Ihren C++ - Code mit Objective-C umschließen und den Objective C-Wrapper in Swift verwenden.

8
Austin

Ich habe auch ein Demoprogramm für Swift opencv kombinieren.

Sie können es von https://github.com/russj/Swift_opencv3_demo herunterladen.

Weitere Informationen zur Demo http://flopalm.com/opencv-with-Swift/ .

4
Russj

Nein, nicht in einer einzigen Datei.

Sie können C++ jedoch in Swift Projekten verwenden, ohne eine statische Bibliothek oder ein Framework zu benötigen. Wie bereits erwähnt, besteht der Schlüssel darin, einen Objective-C-Bridging-Header zu erstellen, der C-kompatible C++ - Header enthält die als C kompatibel mit dem externen "C" {} Trick markiert sind.

Video-Tutorial: https://www.youtube.com/watch?v=0x6JbiphNS4

4
James Mart

Ein Trick (von vielen) ist der

Sie benötigen einen separaten Header für Ihre Bridging-Obj-C++ - Datei ...

Sie können @interface und @implementation nicht einfach in dieselbe .mm-Datei werfen, wie dies normalerweise häufig der Fall ist.

Also hast du in deiner Bridging-Header-Datei

#import "Linkage.hpp"

Linkage.hpp hat die @ Schnittstelle für Linkage und Linkage.mm hat die @ Implementierung für .mm

Und dann

... Sie tatsächlich nicht #include "yourCpp.hpp" in Linkage.hpp.

Sie setzen nur #include "yourCpp.hpp" in der Datei Linkage.mm, nicht in der Datei Linkage.hpp.

In vielen Online-Beispielen/Tutorials fügt der Schreiber einfach die @ -Interface- und die @ -Implementierungsdatei in dieselbe .mm-Datei ein, wie dies häufig der Fall ist.

Das wird in sehr einfachen CPP-Bridging-Beispielen funktionieren, aber,

Das Problem ist:

wenn Ihre yourCpp.hpp irgendwelche C++ - Funktionen hat, die sie sicherlich haben wird (wie die erste Zeile #include <something>), dann schlägt der Prozess fehl.

Aber wenn Sie nur nicht haben die #include "yourCpp.hpp" in der Linkage Kopfzeile Datei (es ist in Ordnung, es in der .mm Datei zu haben, offensichtlich müssen Sie ) - Es klappt.

Auch dies ist leider nur ein Tipp im gesamten Prozess.

2
Fattie

Andere Antworten sind etwas ungenau. Sie können tatsächlich Swift und [Objective-] C [++] in derselben Datei mischen, obwohl dies nicht ganz so ist, wie Sie es erwarten würden.

Diese Datei (c.Swift) kompiliert eine gültige ausführbare Datei mit swiftc c.Swift und 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;
}
// */
2
snake5

Falls dies für jemanden hilfreich ist, habe ich auch ein kurzes Tutorial zum Aufrufen einer einfachen statischen C++ - Bibliothek aus einem einfachen Swift Kommandozeilen-Dienstprogramm. Dies ist ein absoluter Beweis für das Konzept Code.

Kein Objective-C, nur Swift und C++. Code in einer C++ - Bibliothek wird von einem C++ - Wrapper aufgerufen, der eine Funktion mit externer "C" -Verknüpfung implementiert. Auf diese Funktion wird dann im Bridging verwiesen Header und rief von Swift.

Siehe http://www.swiftprogrammer.info/Swift_call_cpp.html

1
Anatoli P

Ich stelle einen Link zu SE-0038 in der offiziellen Ressource bereit, die als beschrieben wird. Dies enthält Vorschläge für Änderungen und für den Benutzer sichtbare Verbesserungen der Swift Programmiersprache.

Der heutige Status ist, dass dies die Feature-Anfrage ist, die akzeptiert, aber noch nicht geplant wurde.

Dieser Link soll alle, die nach dieser Funktion suchen, in die richtige Richtung lenken

1
Ryan Heitner