Je viens de changer mes fichiers .m en .mm et d’utiliser C++. Y at-il un moyen de faire la même chose avec Swift?
Non. Lorsque vous passez de .m à .mm, vous passez réellement d'Objective-C à un autre langage (qui comporte de nombreuses différences subtiles) appelé Objective-C++. Donc, vous n'utilisez pas vraiment le C++; vous utilisez Objective-C++ qui accepte la plupart des entrées C++ (de la même manière que C++ accepte la plupart des entrées C mais pas toutes). Quand je dis que ce n'est pas tout à fait C++, considérons un fichier C++ qui inclut une variable nommée nil
(qui est légal C++), puis essayez de le compiler en tant que 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 dans un fichier .Swift
.
"Utiliser Swift avec Cocoa et Objective-C" nous dit aussi:
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++.
La confusion peut venir de l’hypothèse que changer simplement une extension de fichier de _.m
_ à _.mm
_ est tout ce dont vous avez besoin pour faire le pont entre les langues, alors qu’en réalité, cela ne fait rien. Ce n'est pas le _.mm
_ qui cause des frictions avec _.cpp
_, c'est l'en-tête _.h
_ qui ne doit pas être positivement un en-tête _C++
_.
Dans le projet même, vous pouvez mélanger avec bonheur 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 de _@objc
_ à Objective-C .h
_: c'est la partie la plus délicate, car ils sont utilisés de manière ambiguë pour tous les goûts de C, ++ ou non, Objectif ou non. Quand un _.h
_ ne contient pas un seul mot clé C++ , comme class
, il peut être ajouté au _...Bridging-Header.h
_, et exposera quelle que soit la fonction les fonctionnalités _.c
_ ou _.cpp
_ correspondantes déclarées. Sinon, cet en-tête doit être enveloppé dans un pur C ou Objective-C API.Dans le fichier même, vous ne pouvez pas mélanger tous les 5. Dans le même fichier source :
.Swift
_: vous ne peut 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
_: pure C.cpp
_: vous pouvez mélanger C++ & Assembly (- @ Vality ).h
_: omniprésent et ambigu C, C++ , Objective-C ou Objective-C++ , la réponse est donc - ça dépend.Références
J'ai écrit un simple projet Xcode 6 qui montre comment mélanger C++, Objective C et le code Swift:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
En particulier, l'exemple appelle un objectif C et une fonction C++ à partir de 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.
Je viens de faire un petit exemple de projet utilisant Swift, Objective-C et C++. C’est une démonstration de l’utilisation de la couture OpenCV dans 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 en parler directement. Veillez à ne pas importer indirectement de fichiers C++-ish dans les en-têtes avec lesquels Swift interagit.
Le projet est ici: https://github.com/foundry/OpenCVSwiftStitch
Vous pouvez également ignorer Objective-C fichier entre les deux. Ajoutez simplement un fichier d’en-tête C avec un fichier source .cpp. N'ayez que des déclarations C dans le fichier d'en-tête et incluez le code C++ dans le fichier source. Ensuite, incluez le fichier d’en-tête C dans le fichier ** - Bridging-Header.h.
L'exemple suivant renvoie un pointeur sur un objet C++ (struct Foo) afin que Swift puisse être stocké 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
Dans le 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;
}
Voici ma tentative d'un outil logiciel pour automatiser la communication C++/Swift. 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 Swift combinant ouvertement.
Vous pouvez le télécharger à partir de 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 déjà dit, la clé consiste à créer un en-tête de pontage Objective-C qui # inclut les en-têtes C++ compatibles C marqués comme C compatibles avec le extern "C" {} astuce.
Didacticiel vidéo: https://www.youtube.com/watch?v=0x6JbiphNS4
Une astuce (sur beaucoup) est que
Vous ne pouvez pas simplement jeter @interface et @implementation dans le même fichier .mm comme on le fait souvent.
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 l’implémentation pour .mm
Puis
Vous ne mettez que #include "yourCpp.hpp"
dans le fichier Linkage.mm, not dans le fichier Linkage.hpp.
Dans de nombreux exemples/tutoriels en ligne, le rédacteur place simplement les éléments @interface et @implementation dans le même fichier .mm, comme on le fait souvent.
Cela fonctionnera dans des exemples très simples de pontage cpp, mais,
Le problème est:
si votre yourCpp.hpp possède des fonctionnalités c ++ qui lui seront sûrement utiles (comme la première ligne #include <something>
), le processus échouera.
Mais si vous simplement ne le faites pas avez le #include "yourCpp.hpp"
dans la liaison en-tête fichier (c'est bien de l'avoir dans le fichier .mm, vous en aurez évidemment besoin) - cela fonctionne.
Encore une fois, il ne s'agit malheureusement que d'un conseil dans tout le processus.
Les autres réponses sont légèrement inexactes. Vous pouvez réellement mélanger Swift et [Objective-] C [++] dans le même fichier, mais pas tout à fait comme vous le souhaiteriez.
Ce fichier (c.Swift) est compilé en un exécutable valide avec à la fois swiftc c.Swift
et 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;
}
// */
Au cas où cela serait utile, j’aurai également un bref tutoriel sur l’appel d’une bibliothèque statique C++ simple à partir d’un utilitaire de ligne de commande trivial Swift. Il s’agit d’une pièce de code de preuve de concept vraiment sobre.
Aucun Objective-C impliqué, juste Swift et C++. Le code dans 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 fournis un lien vers SE-0038 dans la ressource officielle, décrite comme suit: . Cette procédure conserve les propositions de modifications et les améliorations visibles par l'utilisateur du Swift. _ Langage de programmation.
L'état 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 ceux qui recherchent cette fonctionnalité dans la bonne direction.