web-dev-qa-db-fra.com

Puis-je mélanger Swift avec C ++? Comme les fichiers Objective - C .mm

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?

126
EhTd

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++.

109
Rob Napier

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++_.


Même projet: oui.

Dans le projet même, vous pouvez mélanger avec bonheur C, C++ , Objective-C , Objective C++ , Swift , et même Assembly .

  1. _...Bridging-Header.h_: vous exposez C, Objective-C et Objective-C++ à Swift en utilisant ce pont
  2. _<ProductModuleName>-Swift.h_: expose automatiquement ​​vos classes Swift marquées de _@objc_ à Objective-C
  3. _.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.

Même dossier: non.

Dans le fichier même, vous ne pouvez pas mélanger tous les 5. Dans le même fichier source :

  1. _.Swift_: vous ne peut pas mélanger Swift avec quoi que ce soit
  2. _.m_: vous pouvez mélanger Objective-C avec C. ( @ Vinzzz )
  3. _.mm_: vous pouvez mélanger Objective-C avec C++ . Ce pont est Objective-C++ . ( @ Vinzzz ).
  4. _.c_: pure C
  5. _.cpp_: vous pouvez mélanger C++ & Assembly (- @ Vality )
  6. _.h_: omniprésent et ambigu C, C++ , Objective-C ou Objective-C++ , la réponse est donc - ça dépend.

Références

159
SwiftArchitect

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.

72
Gian Luigi Romita

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

27
foundry

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;
}
25
Dan G

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++.

https://github.com/sandym/swiftpp

13
Sandy

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.

8
Austin

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/ .

4
Russj

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

4
James Mart

Une astuce (sur beaucoup) est que

Vous avez besoin d'un en-tête séparé pour votre fichier de pontage obj-c ++ ...

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 avez réellement pas #include "yourCpp.hpp" dans Linkage.hpp.

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.

2
Fattie

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;
}
// */
2
snake5

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.

Voir http://www.swiftprogrammer.info/Swift_call_cpp.html

1
Anatoli P

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.

1
Ryan Heitner