Réponses:
Non. Lorsque vous passez de .m à .mm, vous passez en fait d'Objective-C à un autre langage (qui présente de nombreuses différences subtiles) appelé Objective-C ++. Vous n'utilisez donc pas vraiment C ++; vous utilisez Objective-C ++ qui accepte la plupart des C ++ en entrée (de la même manière que C ++ accepte la plupart mais pas tous les C en entrée). Quand je dis que ce n'est pas tout à fait C ++, considérez un fichier C ++ qui comprend une variable nommée nil
(qui est C ++ légal), puis essayez de compiler cela en Objective-C ++.
Swift n'a pas la même relation. Ce n'est pas un sur-ensemble de C ou C ++, et vous ne pouvez pas utiliser directement l'un ou l'autre dans un .swift
fichier.
"Utiliser Swift avec Cocoa et Objective-C" nous dit également:
Vous ne pouvez pas importer du code C ++ directement dans Swift. Au lieu de cela, créez un wrapper Objective-C ou C pour le code C ++.
.mm
vos fichiers et être (presque) terminé. Ce n'est pas le cas avec Swift.
nil
, commeint nil
La confusion peut provenir de l'hypothèse que simplement changer une extension de fichier de .m
à .mm
est tout ce dont vous avez besoin pour relier les langues, alors qu'en réalité, cela ne fait rien de ce genre. Ce n'est pas le .mm
frottement avec .cpp
, c'est le .h
collecteur qui ne doit absolument pas être un C++
collecteur.
Dans le même projet, vous pouvez facilement mélanger C , C ++ , Objective-C , Objective C ++ , Swift et même Assembly .
...Bridging-Header.h
: vous exposez C , Objective-C et Objective-C ++ à Swift en utilisant ce pont<ProductModuleName>-Swift.h
: expose automatiquement vos classes Swift marquées d'un @objc
à Objective-C.h
: c'est la partie la plus délicate, car ils sont utilisés de manière ambiguë pour toutes les saveurs de C , ++ ou pas, Objective ou pas. Quand a .h
ne contient pas un seul mot-clé C ++ , comme class
, il peut être ajouté au ...Bridging-Header.h
, et exposera la fonction correspondante .c
ou les .cpp
fonctionnalités qu'il déclare. Sinon, cet en-tête doit être encapsulé dans une API pure C ou Objective-C .Dans le même fichier, vous ne pouvez pas mélanger tous les 5. Dans le même fichier source :
.swift
: vous ne pouvez pas mélanger Swift avec quoi que ce soit.m
: Vous pouvez mélanger Objective-C avec C . ( @Vinzzz ).mm
: vous pouvez mélanger Objective-C avec C ++ . Ce pont est Objective-C ++ . ( @Vinzzz )..c
: C pur.cpp
: vous pouvez mélanger C ++ et Assembly ( @Vality ).h
: C , C ++ , Objective-C ou Objective-C ++ omniprésent et ambigu , donc la réponse est que cela dépend.Références
J'ai écrit un projet Xcode 6 simple qui montre comment mélanger du code C ++, Objective C et Swift:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
En particulier, l'exemple appelle un Objective C et une fonction C ++ à partir du Swift.
La clé est de créer un en-tête partagé Project-Bridging-Header.h et d'y placer les en-têtes Objective C.
Veuillez télécharger le projet comme exemple complet.
ObjCtoCPlusPlus.h
/ `` .mm` existe dans le seul but de fournir une interface Ob-C au code C ++ - c'est le pont, qui est ici un composant nécessaire. Laissez les includes où ils se trouvent et ajoutez une méthode dans les ObjCtoCPlusPlus.…
fichiers pour chaque méthode C ++ à laquelle vous devez accéder. Vous feriez bien de lire sur sourcemaking.com/design_patterns/adapter
Vous pouvez également ignorer le fichier Objective-C entre les deux. Ajoutez simplement un fichier d'en-tête C avec un fichier source .cpp. Avoir uniquement des déclarations C dans le fichier d'en-tête et inclure tout code C ++ dans le fichier source. Incluez ensuite le fichier d'en-tête C dans le ** - Bridging-Header.h.
L'exemple suivant renvoie un pointeur vers un objet C ++ (struct Foo) afin que Swift puisse stocker dans un COpaquePointer au lieu d'avoir struct Foo défini dans l'espace global.
Fichier Foo.h (vu par Swift - inclus dans le fichier de pontage)
#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
À l'intérieur du fichier source Foo.cpp (non vu par 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"
envelopper l'en-tête à l'endroit où il est inclus plutôt #ifdef
qu'éd dans le fichier d'en-tête lui-même. Brillant!
Je viens de faire un petit exemple de projet utilisant Swift, Objective-C et C ++. C'est une démonstration de l'utilisation de l'assemblage OpenCV sous iOS. L'API OpenCV est C ++, nous ne pouvons donc pas lui parler directement depuis Swift. J'utilise une petite classe wrapper dont le fichier d'implémentation est Objective-C ++. Le fichier d'en- tête est propre Objective-C, donc Swift peut lui parler directement. Vous devez faire attention à ne pas importer indirectement de fichiers C ++ dans les en-têtes avec lesquels Swift interagit.
Le projet est ici: https://github.com/foundry/OpenCVSwiftStitch
Voici ma tentative d'un outil clang pour automatiser la communication C ++ / rapide. Vous pouvez instancier des classes C ++ à partir de swift, hériter de la classe C ++ et même remplacer des méthodes virtuelles dans swift.
Il analysera la classe C ++ que vous souhaitez exporter vers swift et générera automatiquement le pont Objective-C / Objective-C ++.
Swift n'est pas directement compatible avec C ++. Vous pouvez contourner le problème en encapsulant votre code C ++ avec Objective-C et en utilisant l'encapsuleur Objective C dans Swift.
J'ai aussi un programme de démonstration pour opencv de combinaison rapide.
Vous pouvez le télécharger sur https://github.com/russj/swift_opencv3_demo .
Plus d'informations sur la démo http://flopalm.com/opencv-with-swift/ .
Non, pas dans un seul fichier.
Cependant, vous pouvez utiliser C ++ dans Swift Projects sans avoir besoin d'une bibliothèque statique ou d'un framework. Comme d'autres l'ont dit, la clé est de créer un en-tête de pontage Objective-C qui #inclut des en-têtes C ++ compatibles C qui sont marqués comme C compatibles avec l' astuce extern "C" {} .
Tutoriel vidéo: https://www.youtube.com/watch?v=0x6JbiphNS4
D'autres réponses sont légèrement inexactes. Vous pouvez en fait mélanger Swift et [Objective-] C [++] dans le même fichier, mais pas tout à fait comme vous le souhaiteriez.
Ce fichier (c.swift) se compile en un exécutable valide avec à la fois swiftc c.swift
etclang -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 truc (parmi tant d'autres) est que
Vous ne pouvez pas simplement lancer @interface et @implementation dans le même fichier .mm comme on le fait souvent normalement.
Donc, dans votre fichier d'en-tête de pontage, vous avez
#import "Linkage.hpp"
Linkage.hpp a l '@interface pour Linkage et Linkage.mm a la @implementation pour .mm
Puis
Vous ne mettez que #include "yourCpp.hpp"
dans le fichier Linkage.mm, pas dans le fichier Linkage.hpp.
Dans de nombreux exemples / tutoriels en ligne, le rédacteur place simplement @interface et @implementation dans le même fichier .mm, comme on le fait souvent.
Cela fonctionnera dans des exemples de pontage cpp très simples, mais,
Le problème est:
si votre yourCpp.hpp a des fonctionnalités C ++, ce qu'il sera sûrement (comme la première ligne #include <something>
), alors le processus échouera.
Mais si vous n'avez tout simplement pas le #include "yourCpp.hpp"
dans le fichier d'en- tête Linkage (c'est bien de l'avoir dans le fichier .mm, vous en aurez évidemment besoin) - cela fonctionne.
Encore une fois, ce n'est malheureusement qu'un conseil dans l'ensemble du processus.
Au cas où cela serait utile à quiconque, j'ai également un bref tutoriel sur l'appel d'une simple bibliothèque statique C ++ à partir d'un utilitaire de ligne de commande Swift trivial. Il s'agit d'une preuve de concept très simple.
Aucun Objective-C impliqué, juste Swift et C ++. Le code d'une bibliothèque C ++ est appelé par un wrapper C ++ qui implémente une fonction avec une liaison externe "C". Cette fonction est ensuite référencée dans l'en-tête de pontage et appelée depuis Swift.
Je propose un lien vers SE-0038 dans la ressource officielle, décrit comme Ceci maintient les propositions de changements et d'améliorations visibles par l'utilisateur du langage de programmation Swift.
Le statut actuel est qu'il s'agit de la demande de fonctionnalité qui a été acceptée mais pas encore planifiée.
Ce lien est destiné à orienter tous ceux qui recherchent cette fonctionnalité dans la bonne direction