web-dev-qa-db-fra.com

Puis-je avoir des fichiers Swift, Objective-C, C et C ++ dans le même projet Xcode?

Les 4 langues peuvent-elles être utilisées dans le même projet, et si oui, comment?

Il y a des questions similaires dans la version: Puis-je mélanger Swift avec C++? Comme pour l'objectif - C .mm auxquels la réponse acceptée est no .

En utilisant Bridging Header adéquatement, .h qui ne contient pas C++ déclarations, Objective-C wrappers quand .h contient-il C++, .mm fichiers pour effectuer le wrapping de C++ classes et .Swift, peut-on utiliser les 4 langues (5 si vous incluez Objective-C++) construire et lier dans un seul exécutable?


objectif-c ++xcode

61
SwiftArchitect

OUI.

Vous pouvez mélanger Swift, C, C++, Objective-C & Objective-C++ Dans le même projet Xcode.

C

// Declaration: C.h
#ifndef C_h
#define C_h
#ifdef __cplusplus
extern "C" {
#endif
    void hello_c(const char * name);
#ifdef __cplusplus
}
#endif
#endif /* C_h */

// Definition: C.c
#include "C.h"
#include <stdio.h>
void hello_c(const char * name) {
    printf("Hello %s in C\n", name);
}

C++

// Declaration: CPP.hpp
#pragma once
#include <string>
class CPP {
public:
    void hello_cpp(const std::string& name);
};

// Definition: CPP.cpp
#include "CPP.hpp"
#include <iostream>
using namespace std;
void CPP::hello_cpp(const std::string& name) {
    cout << "Hello " << name << " in C++" << endl;
}

Wrapper Objective-C pour C++

// Declaration: CPP-Wrapper.h
#import <Foundation/Foundation.h>
@interface CPP_Wrapper : NSObject
- (void)hello_cpp_wrapped:(NSString *)name;
@end

// Definition: CPP-Wrapper.mm
#import "CPP-Wrapper.h"
#include "CPP.hpp"
@implementation CPP_Wrapper
- (void)hello_cpp_wrapped:(NSString *)name {
    CPP cpp;
    cpp.hello_cpp([name cStringUsingEncoding:NSUTF8StringEncoding]);
}
@end

Objectif c

// Declaration: Objective-C.h
#import <Foundation/Foundation.h>
@interface Objective_C : NSObject
- (void)hello_objectiveC:(NSString *)name;
@end

// Definition: Objective-C.m
#import "Objective-C.h"
@implementation Objective_C
- (void)hello_objectiveC:(NSString*)name {
    printf("Hello %s in Objective-C\n", [name cStringUsingEncoding:NSUTF8StringEncoding]);
}
@end

Objective-C++

// Declaration: Objective-CPP.h
#import <Foundation/Foundation.h>
@interface Objective_CPP : NSObject
- (void)hello_objectiveCpp:(NSString *)name;
@end

// Definition: Objective-CPP.mm
#include <iostream>
#import "Objective-CPP.h"
using namespace std;
@implementation Objective_CPP
- (void)hello_objectiveCpp:(NSString *)name {
    cout << "Hello " << [name cStringUsingEncoding:NSUTF8StringEncoding] << " in Objective-C++\n";
}
@end

Swift

// Declaration & definition: Swift.swift
func hello_Swift(_ name: String) {
    print("Hello \(name) in Swift")
}

Bridging-Header.h

Impossible d'importer le fichier d'en-tête CPP.hpp, Non à cause de sa convention de dénomination, mais parce qu'il contient le mot clé class.

#import "C.h"
#import "CPP-Wrapper.h"
#import "Objective-C.h"
#import "Objective-CPP.h"

Invocation de Swift

// Invoke C
hello_c("World".cStringUsingEncoding(NSUTF8StringEncoding))

// Can't Invoke C++ without a wrapper
// CPP().hello_cpp("World".cStringUsingEncoding(NSUTF8StringEncoding))
// Invoke C++ through Objective-C
CPP_Wrapper().hello_cpp_wrapped("World")

// Invoke Objective-C
Objective_C().hello_objectiveC("World")

// Invoke Objective-C++
Objective_CPP().hello_objectiveCpp("World")

// Invoke Swift
Swift().hello_Swift("World")

.h (en-têtes)

(Voir élément 3 dans cette réponse de débordement de pile )

.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, Objective ou non. Lorsqu'un .h ne contient pas un seul mot-clé C++, tel que classe, il peut être ajouté à ... Bridging-Header.h, et exposera quelle que soit sa fonction, les fonctionnalités correspondantes déclarées. Sinon, cet en-tête doit être encapsulé dans une API pur C ou Objective-C.

Sortie

Hello World in C
Hello World in C++
Hello World in Objective-C
Hello World in Objective-C++
Hello World in Swift

Commentaires

Cy-4AH:

Oui. Vous n'avez besoin que d'envelopper C++ Dans C ou Objective-C Pour l'utiliser dans Swift.

Tommy

En effet, j'ai un projet qui fait exactement cela. C++ Pour les éléments abstraits du modèle multiplate-forme avec quelques C parties dessous; Objective-C Pour envelopper les classes C++ À des fins Swift, Swift pour lier tout cela à une sous-classe de NSDocument, avec des vues personnalisées qui interroge le C truc.

MaddTheSane

Ajout du wrapper extern "C" Selon votre excellente suggestion. Pour invoquer la méthode [~ # ~] c [~ # ~] void hello_c(const char * name) depuis C++ méthode hello_cpp(const std::string& name), ajoutez #include "C.h" Et appelez hello_c(name.c_str());.

Keith Adler

Le nouveau SO-32541268: Maintenant avec les paramètres!


► Trouvez cette solution sur GitHub et des détails supplémentaires sur Swift Recipes .

118
SwiftArchitect