web-dev-qa-db-ja.com

同じXcodeプロジェクトにSwift、Objective-C、C、およびC ++ファイルを含めることはできますか?

4つの言語すべてを同じプロジェクトで使用できますか?

フレーバーには似た質問があります: C++とSwiftを混在させることはできますか? Objective-Cの.mmファイル と同様に、受け入れられる答えはnoです。

Bridging Headerを適切に使用し、.hステートメントを含まないC++Objective-C.hC++ファイルを含む場合の.mmラッパーC++クラスと.Swiftの実際のラッピングを行うには、4つの言語(Objective-C++を含めると5つ)をビルドして単一の実行可能ファイルにリンクできますか?


objective-c ++xcode

61
SwiftArchitect

はい。

同じXcodeプロジェクトにSwiftC、_C++_、_Objective-C_および_Objective-C++_ファイルを混在させることができます。

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;
}
_

C++用のObjective-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
_

Objective-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

_CPP.hpp_ヘッダーファイルはインポートできません。命名規則のためではなく、classキーワードが含まれているためです。

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

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(ヘッダー)

item 3 in this Stack Overflow answer を参照)

.h:これはトリッキーな部分です。これは、C++の有無にかかわらず、Objectiveかどうかにかかわらず、Cのすべてのフレーバーに曖昧に使用されているためです。 .hがクラスのような単一のC++キーワードを含まない場合、... Bridging-Header.hに追加でき、対応する.cまたは.cpp機能が宣言するすべての機能を公開します。それ以外の場合、そのヘッダーは純粋なCまたはObjective-C APIでラップする必要があります。

出力

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

コメント

Cy-4AH

はい。 Cで使用するには、_C++_をSwiftまたは_Objective-C_にラップするだけです。

トミー

実際、まさにそれを行うプロジェクトがあります。 _C++_は、いくつかのCパーツが下にある抽象的なクロスプラットフォームモデルの要素の推進力です。 _Objective-C_はSwiftの目的で_C++_クラスをラップし、SwiftNSDocumentのサブクラスにすべてをバインドし、Cもの。

MaddTheSane

あなたの素晴らしい提案に従って_extern "C"_ラッパーを追加しました。 [〜#〜] c [〜#〜]メソッドvoid hello_c(const char * name)から呼び出すにはC++メソッドhello_cpp(const std::string& name)、_#include "C.h"_を追加し、hello_c(name.c_str());を呼び出します。

キース・アドラー

new SO-32541268:パラメータ付き!


GitHub でこのソリューションを見つけ、 Swift Recipes で追加の詳細を見つけてください。

118
SwiftArchitect