【问题标题】:Can I have Swift, Objective-C, C and C++ files in the same Xcode project?我可以在同一个 Xcode 项目中拥有 Swift、Objective-C、C 和 C++ 文件吗?
【发布时间】:2015-12-09 01:34:35
【问题描述】:

是否可以在同一个项目中使用所有 4 种语言,如果可以,如何使用?

类似 风格的问题:Can I mix Swift with C++? Like the Objective - C .mm files 接受的答案是

充分使用Bridging Header.h 不包含C++ 语句,Objective-C 包装器当.h 包含C++.mm 文件执行C++ 类的实际包装,和 .swift,这 4 种语言(如果包括 Objective-C++,则为 5 种语言)可以构建并链接到单个可执行文件中吗?


【问题讨论】:

  • 是的。您只需将C++ 包装成CObjective-C 即可在Swift 中使用。
  • 确实,我有一个项目可以做到这一点。 C++ 用于抽象跨平台模型的推动力,下面有一些 C 部分; Objective-C 为 Swift 目的包装 C++ 类,Swift 将所有这些绑定到 NSDocument 的子类,并带有一些询问 C 内容的自定义视图。

标签: objective-c++ xcode c++ objective-c c swift bridging-header


【解决方案1】:

是的。

您可以在同一个 Xcode 项目中混合使用 SwiftCC++Objective-CObjective-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

目标-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

斯威夫特

// 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(标题)

(参见this Stack Overflow answer 中的第 3 项

.h:这是棘手的部分,因为它们被模棱两可地用于所有类型的 C、++ 与否、Objective 与否。当 .h 不包含单个 C++ 关键字(如 class)时,可以将其添加到 ...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++ 包装成CObjective-C 即可在Swift 中使用。

Tommy

确实,我有一个项目可以做到这一点。 C++ 用于抽象跨平台模型的主旨,下面有一些 C 部分; Objective-C 包装 C++ 类用于 Swift 目的,Swift 将所有这些绑定到 NSDocument 的子类,并带有一些询问 C 内容的自定义视图。

MaddTheSane

根据您的出色建议添加了 extern "C" 包装器。要从 C++ 方法 hello_cpp(const std::string&amp; name) 调用 C 方法 void hello_c(const char * name),请添加 #include "C.h" 并调用 hello_c(name.c_str());

Keith Adler

新的SO-32541268:现在带有参数!


► 在GitHub 上查找此解决方案,在Swift Recipes 上查找更多详细信息。

【讨论】:

  • +1 - 令人惊叹的答案,但真正令人遗憾的是,简单的 C++ 方法没有将指针或对另一个 C++ 对象的引用作为参数 - 这就是我的想法。
  • 请注意,如果在 C++ 源代码中包含并调用 C 函数,则可能需要将 C 函数包装在 extern "C" { } 中。这也意味着您可以拥有一个在 C++ 中实现并在 Swift 中调用的符合 C 标准的函数。
  • @SwiftArchitect 这绝对是一个很好的例子,但我认为如果你在目标 c++ 包装器的 .h 文件中包含 它将不适合我
  • @SwiftArchitect 这仍然有效吗? #include &lt;string&gt; 在 CPP.hpp 中产生以下错误 'string' file not found
  • @SwiftArchitect 我明白了我的问题所在。我将CPP-Wrapper 命名为 .m 而不是 .mm 您可能希望将“Objective-C wrapper for C++”标题更改为“Objective-C++ wrapper for C++”。即使您在 cmets 中有以 .mm 结尾的文件名,如果有人(像我一样)创建了一个 .m,那么 #include &lt;string&gt; 在 CPP.hpp 中会产生以下错误 'string' file not found。感谢这个伟大的资源。 :-)
猜你喜欢
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2013-12-05
  • 1970-01-01
  • 2014-07-23
  • 2018-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多