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 .swift
file.
"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 ++.
.mm
tuoi 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 .m
a .mm
è tutto ciò che serve per colmare le lingue, quando, in realtà, non fa nulla del genere. Non è quello .mm
che causa attrito .cpp
, è l' .h
intestazione 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 @objc
a 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 .h
non 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.swift
eclang -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