Antworten:
Nein. Wenn Sie von .m zu .mm wechseln, wechseln Sie tatsächlich von Objective-C zu einer anderen Sprache (die viele subtile Unterschiede aufweist) namens Objective-C ++. Sie verwenden C ++ also nicht wirklich. 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
(was legal C ++ ist) enthält, 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 keine direkt in einer .swift
Datei verwenden.
"Swift mit Kakao und Objective-C verwenden" 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.
.mm
Ihre Dateien durchsuchen und (fast) fertig sein. Nicht so bei Swift.
nil
, wieint nil
Die Verwirrung kann von der Annahme herrühren, dass das bloße Ändern einer Dateierweiterung von .m
in .mm
alles ist, was Sie benötigen, um die Sprachen zu überbrücken, wenn dies in Wirklichkeit nichts dergleichen bewirkt. Es ist nicht das .mm
, was Reibung verursacht .cpp
, es ist der .h
Header, der definitiv kein Header sein darf C++
.
Im selben Projekt können Sie problemlos C , C ++ , Objective-C , Objective C ++ , Swift und sogar Assembly mischen .
...Bridging-Header.h
: Sie belichten C , Objective-C und Objective-C ++ zu Swift mit dieser Brücke<ProductModuleName>-Swift.h
: Setzt automatisch Ihre Swift Klassen markiert mit @objc
zu Objective-C.h
: Dies ist der schwierige Teil, da sie für alle Varianten von C , ++ oder nicht, Objective oder nicht mehrdeutig verwendet werden . Wenn a .h
kein einziges C ++ - Schlüsselwort enthält, wie z. B. class
, kann es dem hinzugefügt ...Bridging-Header.h
werden und macht die entsprechende Funktion .c
oder die von .cpp
ihm deklarierten Funktionen verfügbar. Andernfalls muss dieser Header entweder in eine reine C- oder eine Objective-C- API eingeschlossen werden.In derselben Datei können Sie nicht alle 5 mischen. In derselben Quelldatei :
.swift
: Sie können Swift mit nichts mischen.m
: Sie können Objective-C mit C mischen . ( @Vinzzz ).mm
: Sie können Objective-C mit C ++ mischen . Diese Brücke ist Objective-C ++ . ( @Vinzzz )..c
: reines C..cpp
: Sie können C ++ & Assembly ( @Vality ) mischen.h
: allgegenwärtiges und mehrdeutiges C , C ++ , Objective-C oder Objective-C ++ , also hängt die Antwort davon ab.Verweise
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 aus dem Swift auf.
Der Schlüssel besteht darin, einen gemeinsamen Header Project-Bridging-Header.h zu erstellen und die Objective C-Header dort abzulegen.
Bitte laden Sie das Projekt als vollständiges Beispiel herunter.
ObjCtoCPlusPlus.h
/ `` .mm` dient ausschließlich dem Zweck, eine Ob-C-Schnittstelle für C ++ - Code bereitzustellen - es ist die Brücke, die hier eine notwendige Komponente darstellt. Lassen Sie die Includes dort, wo sie sich befinden, und fügen Sie ObjCtoCPlusPlus.…
für jede C ++ - Methode, auf die Sie Zugriff benötigen , eine Methode in die Dateien ein. Sie sollten gut über sourcemaking.com/design_patterns/adapter
Sie können auch die Objective-C- Datei dazwischen überspringen . Fügen Sie einfach eine C-Header-Datei mit einer CPP-Quelldatei hinzu. Haben Sie nur C-Deklarationen in der Header-Datei und fügen Sie C ++ - Code in die Quelldatei ein. 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, damit Swift in einem COpaquePointer speichern kann, anstatt struct Foo im globalen Raum definiert zu haben.
Foo.h-Datei (von Swift gesehen - in der Bridging-Datei enthalten)
#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;
}
extern "C"
der Header an der Stelle verpackt wird, an der er enthalten ist, anstatt #ifdef
in der Header-Datei selbst enthalten zu sein. Brillant!
Ich habe gerade ein kleines Beispielprojekt mit Swift, Objective-C und C ++ erstellt. Es ist eine Demo zur Verwendung von OpenCV-Stitching in iOS. Die OpenCV-API ist C ++, daher können wir nicht direkt von Swift aus mit ihr kommunizieren. Ich verwende eine kleine Wrapper-Klasse, deren Implementierungsdatei Objective-C ++ ist. Die Header- Datei ist sauberes Objective-C, sodass Swift direkt damit sprechen kann. Sie müssen darauf achten, keine indirekten C ++ - Dateien in die Header zu importieren, mit denen Swift interagiert.
Das Projekt ist hier: https://github.com/foundry/OpenCVSwiftStitch
Hier ist mein Versuch eines Clang-Tools zur Automatisierung der C ++ / schnellen Kommunikation. Sie können C ++ - Klassen von Swift aus instanziieren, von C ++ - Klassen erben und sogar virtuelle Methoden in Swift überschreiben.
Es analysiert die C ++ - Klasse, die Sie exportieren möchten, um die Objective-C / Objective-C ++ - Brücke schnell zu generieren und automatisch zu generieren.
Swift ist nicht direkt mit C ++ kompatibel. Sie können das Problem umgehen, indem Sie Ihren C ++ - Code mit Objective-C umbrechen und den Objective C-Wrapper in Swift verwenden.
Ich habe auch ein Demo-Programm für die schnelle Kombination von OpenCV.
Sie können es von https://github.com/russj/swift_opencv3_demo herunterladen .
Weitere Informationen zur Demo finden Sie unter http://flopalm.com/opencv-with-swift/ .
Nein, nicht in einer einzigen Datei.
Sie können C ++ jedoch in Swift-Projekten verwenden, ohne eine statische Bibliothek oder ein statisches Framework zu benötigen. Wie andere bereits gesagt haben, 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" markiert sind {} Trick .
Video-Tutorial: https://www.youtube.com/watch?v=0x6JbiphNS4
Andere Antworten sind etwas ungenau. Sie können Swift und [Objective-] C [++] tatsächlich in derselben Datei mischen, allerdings nicht ganz so, wie Sie es erwarten würden.
Diese Datei (c.swift) wird mit swiftc c.swift
und zu einer gültigen ausführbaren Datei kompiliertclang -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;
}
// */
Ein Trick (von vielen) ist der
Sie können @interface und @implementation nicht einfach in dieselbe .mm-Datei werfen, wie dies normalerweise häufig der Fall ist.
Also in Ihrer Bridging-Header-Datei haben Sie
#import "Linkage.hpp"
Linkage.hpp hat die @ Schnittstelle für Linkage und Linkage.mm hat die @ Implementierung für .mm
Und dann
Sie geben nur #include "yourCpp.hpp"
die Datei Linkage.mm ein, nicht die Datei Linkage.hpp.
In vielen Online-Beispielen / Tutorials fügt der Autor die @ Schnittstelle und die @ Implementierung einfach in dieselbe .mm-Datei ein, wie dies häufig der Fall ist.
Das wird in sehr einfachen cpp-Überbrückungsbeispielen funktionieren, aber
Das Problem ist:
Wenn Ihre yourCpp.hpp überhaupt C ++ - Funktionen hat, die sie sicherlich haben wird (wie die erste Zeile #include <something>
), schlägt der Prozess fehl.
Aber wenn Sie nur nicht die haben #include "yourCpp.hpp"
in der Linkage - Header - Datei (es ist in Ordnung in der .mm Datei haben, natürlich werden Sie müssen) - es funktioniert.
Auch dies ist leider nur ein Tipp im gesamten Prozess.
Falls dies für jemanden hilfreich ist, habe ich auch ein kurzes Tutorial zum Aufrufen einer einfachen statischen C ++ - Bibliothek über ein triviales Swift-Befehlszeilenprogramm. Dies ist ein wirklich nackter Proof-of-Concept-Code.
Kein Objective-C beteiligt, nur Swift und C ++. Code in einer C ++ - Bibliothek wird von einem C ++ - Wrapper aufgerufen, der eine Funktion mit externer "C" -Verknüpfung implementiert. Diese Funktion wird dann im Bridging-Header referenziert und von Swift aufgerufen.
Ich stelle einen Link zu SE-0038 in der offiziellen Ressource bereit , die als Dies enthält Vorschläge für Änderungen und vom Benutzer sichtbare Verbesserungen der Swift-Programmiersprache.
Der heutige Status ist, dass dies die Funktionsanforderung ist, die akzeptiert, aber noch nicht geplant wurde.
Dieser Link soll jeden, der nach dieser Funktion sucht, in die richtige Richtung lenken