一尘不染

我可以在同一个Xcode项目中拥有Swift,Objective-C,C和C ++文件吗?

swift

可以在同一项目中完全使用所有4种语言吗?

这个风格也有类似的问题:我可以将Swift与C ++混合使用吗?类似于
Objective-C .mm文件,对于该文件,可接受的答案
为否。

Bridging Header适当地使用.h不包含C语句的语句,
Objective-C何时.h包含的包装器C
,.mm用于
实际包装C类的文件以及.swift,这4种语言(如果
包含,则为5种Objective-C
)能否构建并链接到单个可执行文件中?


阅读 277

收藏
2020-07-07

共1个答案

一尘不染

YES.

您可以混合使用SwiftCC++Objective-CObjective-C++中的文件相同的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;
}

Objective-C wrapper for 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

Cannot importCPP.hpp header file, not because of it’s naming convention,
but because it contains the class keyword.

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

Invocation from 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 (Headers)

(See item 3 in this Stack Overflow
answer
)

.h: this is the tricky part, since they are ambiguously used for all flavors
of C, or not, Objective or not. When a .h does not contain a single C
keyword, like class, it can be added to the …Bridging-Header.h, and will
expose whatever function the corresponding .c or .cpp functionalities it
declares. Otherwise, that header must be wrapped in either a pure C or
Objective-C API.

Output

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

Comments

Cy-4AH :

Yes. You only need wrap C++ into C or Objective-C to use in Swift.

Tommy

Indeed, I have a project that does exactly that. C++ for the thrust of the
abstract cross-platform model stuff with some C parts underneath;
Objective-C to wrap the C++ classes for Swift purposes, Swift to bind
all that to a subclass of NSDocument, with some custom views that
interrogate the C stuff.

MaddTheSane

Added the extern "C" wrapper as per your excellent suggestion. To invoke the
C method void hello_c(const char * name) from C++ method
hello_cpp(const std::string& name), add #include "C.h" and call
hello_c(name.c_str());.

Keith Adler

The newSO-32541268: Now
with parameters!


► Find this solution on
GitHub and additional details
on Swift Recipes.

2020-07-07