Risposte:
No. Quando passi da .m a .mm stai effettivamente passando da Objective-C a un linguaggio diverso (che presenta molte differenze sottili) chiamato Objective-C ++. Quindi non stai davvero usando C ++; stai usando Objective-C ++ che accetta la maggior parte del C ++ come input (nello stesso modo in cui C ++ accetta la maggior parte, ma non tutti i C come input). Quando dico che non è proprio C ++, considera un file C ++ che include una variabile denominata nil(che è C ++ legale) e quindi prova a compilarlo come Objective-C ++.
Swift non ha la stessa relazione. Non è un superset di C o C ++ e non è possibile utilizzarlo direttamente in un .swiftfile.
"Uso di Swift con Cocoa e Objective-C" ci dice anche:
Non è possibile importare il codice C ++ direttamente in Swift. Invece, creare un wrapper Objective-C o C per il codice C ++.
.mmtuoi file ed essere (quasi) fatto. Non così con Swift.
nil, comeint nil
La confusione può derivare dal presupposto che semplicemente cambiare un'estensione di file da .ma .mmè tutto ciò che serve per colmare le lingue, quando, in realtà, non fa nulla del genere. Non è quello .mmche causa attrito .cpp, è l' .hintestazione che non deve essere positivamente C++un'intestazione.
Nello stesso progetto, puoi tranquillamente mescolare C , C ++ , Objective-C , Objective C ++ , Swift e persino Assembly .
...Bridging-Header.h: esponi C , Objective-C e Objective-C ++ su Swift usando questo bridge<ProductModuleName>-Swift.h: Espone automaticamente i tuoi Swift classi contrassegnati con @objca Objective-C.h: questa è la parte difficile, dal momento che sono ambiguamente usati per tutti i gusti di C , ++ o no, Obiettivo o no. Quando a .hnon contiene una singola parola chiave C ++ , come class, può essere aggiunta a ...Bridging-Header.h, ed esporrà qualunque funzione le corrispondenti .c o .cpp funzionalità che dichiara. Altrimenti, quell'intestazione deve essere racchiusa in un'API C o Objective-C pura .Nello stesso file, non è possibile mescolare tutti 5. Nello stesso file di origine :
.swift: non puoi mescolare Swift con niente.m: Potete mescolare Objective-C con C . ( @Vinzzz ).mm: puoi mescolare Objective-C con C ++ . Questo bridge è Objective-C ++ . ( @Vinzzz )..c: puro C.cpp: puoi mescolare C ++ e Assembly ( @Vality ).h: onnipresente e ambiguo C , C ++ , Objective-C o Objective-C ++ , quindi la risposta è che dipende.Riferimenti
Ho scritto un semplice progetto Xcode 6 che mostra come mescolare codice C ++, Objective C e codice Swift:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
In particolare, l'esempio chiama Swift da un obiettivo C e una funzione C ++.
La chiave è creare un'intestazione condivisa Project-Bridging-Header.h e inserire lì le intestazioni dell'Obiettivo C.
Si prega di scaricare il progetto come esempio completo.
ObjCtoCPlusPlus.h/ `` .mm` esiste al solo scopo di fornire un'interfaccia Ob-C al codice C ++ - è il bridge, che è un componente necessario qui. Lasciare le inclusioni dove si trovano e aggiungere un metodo nei ObjCtoCPlusPlus.…file per ciascun metodo C ++ a cui è necessario accedere. Faresti bene a leggere su sourcemaking.com/design_patterns/adapter
Puoi anche saltare il file Objective-C tra. Basta aggiungere un file di intestazione C con un file di origine .cpp. Includere solo dichiarazioni C nel file di intestazione e includere qualsiasi codice C ++ nel file di origine. Quindi includere il file di intestazione C in ** - Bridging-Header.h.
L'esempio seguente restituisce un puntatore a un oggetto C ++ (struct Foo) in modo che Swift possa archiviare in un COpaquePointer invece di avere Struct Foo definito nello spazio globale.
File Foo.h (visto da Swift - incluso nel file ponte)
#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
All'interno del file sorgente Foo.cpp (non visto da Swift):
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"avvolgere l'intestazione nel punto in cui è inclusa anziché #ifdef"ed" nel file di intestazione stesso. Brillante!
Ho appena realizzato un piccolo esempio di progetto usando Swift, Objective-C e C ++. È una demo di come utilizzare le cuciture OpenCV in iOS. L'API OpenCV è C ++ quindi non possiamo parlarne direttamente da Swift. Uso una piccola classe wrapper il cui file di implementazione è Objective-C ++. Il file Header è pulito Objective-C, quindi Swift può parlarne direttamente. Bisogna fare attenzione a non importare indirettamente alcun file C ++ nelle intestazioni con cui Swift interagisce.
Il progetto è qui: https://github.com/foundry/OpenCVSwiftStitch
Ecco il mio tentativo di uno strumento clang per automatizzare la comunicazione C ++ / swift. Puoi instanciare le classi C ++ da swift, ereditare dalla classe C ++ e persino sovrascrivere i metodi virtuali in swift.
Analizzerà la classe C ++ che si desidera esportare in modo rapido e genererà automaticamente il bridge Objective-C / Objective-C ++.
Swift non è direttamente compatibile con C ++. Puoi aggirare il problema avvolgendo il tuo codice C ++ con Objective-C e usando il wrapper Objective C in Swift.
Ho anche un programma demo per combinare rapidamente Opencv.
Puoi scaricarlo da https://github.com/russj/swift_opencv3_demo .
Maggiori informazioni sulla demo http://flopalm.com/opencv-with-swift/ .
No, non in un singolo file.
Tuttavia, è possibile utilizzare C ++ nei progetti Swift senza la necessità di una libreria o framework statici. Come altri hanno già detto, la chiave è creare un'intestazione bridge Objective-C che includa le intestazioni C ++ compatibili con C che sono contrassegnate come C compatibili con il trucco esterno "C" {} .
Esercitazione video: https://www.youtube.com/watch?v=0x6JbiphNS4
Altre risposte sono leggermente imprecise. Puoi effettivamente mescolare sia Swift che [Objective-] C [++] nello stesso file, anche se non esattamente come ti aspetteresti.
Questo file (c.swift) viene compilato in un eseguibile valido con entrambi swiftc c.swifteclang -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;
}
// */
Un trucco (di molti) è quello
Non puoi semplicemente lanciare @interface e @implementation nello stesso file .mm come si fa normalmente.
Quindi nel tuo file di intestazione ponte hai
#import "Linkage.hpp"
Linkage.hpp ha @interface per Linkage e Linkage.mm ha @implementation per .mm
E poi
#include "yourCpp.hpp"Inserisci solo il file Linkage.mm, non il file Linkage.hpp.
In molti esempi / tutorial online, lo scrittore inserisce semplicemente @interface e @implementation nello stesso file .mm, come si fa spesso.
Funzionerà in esempi di bridge cpp molto semplici, ma,
Il problema è:
se yourCpp.hpp ha funzionalità c ++ che sicuramente avrà (come la prima riga #include <something>), il processo fallirà.
Ma se semplicemente non hai il file di intestazione#include "yourCpp.hpp" Linkage (va bene averlo nel file .mm, ovviamente dovrai farlo) - funziona.
Ancora una volta, questo è purtroppo solo un suggerimento nell'intero processo.
Se questo è utile a chiunque, ho anche un breve tutorial su come chiamare una semplice libreria statica C ++ da una banale utility da riga di comando Swift. Questa è una prova davvero concisa del concetto di codice.
Nessun obiettivo-C coinvolto, solo Swift e C ++. Il codice in una libreria C ++ viene chiamato da un wrapper C ++ che implementa una funzione con collegamento "C" esterno. Tale funzione viene quindi indicata nell'intestazione del bridge e chiamata da Swift.
Sto fornendo un collegamento a SE-0038 nella risorsa ufficiale, descritto come Questo mantiene proposte di modifiche e miglioramenti visibili all'utente al linguaggio di programmazione Swift.
Lo stato attuale è che questa è la richiesta di funzionalità che è stata accettata ma non ancora pianificata.
Questo link ha lo scopo di guidare chiunque cerchi questa funzione nella giusta direzione