我可以将 Swift 和 C + + 混合使用吗

我刚刚改变了我的。M 文件。毫米和使用 C + + 。有办法对斯威夫特做同样的事吗?

94638 次浏览

没有。当你从。我去。毫米你实际上是从 Objective-C 切换到一种不同的语言(有很多细微的差别)称为 Objective-C + + 。所以你并没有真正使用 C + + ; 你使用的是 Objective-C + + ,它接受大部分 C + + 作为输入(就像 C + + 接受大部分但不是全部 C 作为输入一样)。当我说它不完全是 C + + 时,考虑一个包含一个名为 nil(这是合法的 C + +)的变量的 C + + 文件,然后尝试将它编译为 Objective-C + + 。

斯威夫特没有这种关系。它不是 C 或 C + + 的超集,也不能直接在 .swift文件中使用。

“用可可和 Objective-C 搭配 Swift” 也告诉我们:

您不能直接将 C + + 代码导入 Swift,而是为 C + + 代码创建一个 Objective-C 或 C 包装器。

Swift 与 C + + 不能直接兼容。您可以通过使用 Objective-C 包装您的 C + + 代码,并在 Swift 中使用 Objective C 包装器来解决这个问题。

我刚刚用 Swift,Objective-C 和 C + + 做了一个小的示例项目。这是一个如何在 iOS 中使用 OpenCV 拼接的演示。OpenCV API 是 C + + 的,所以我们不能直接从 Swift 上访问它。我使用一个小的包装器类,它的实现文件是 Objective-C + + 。文件是干净的 Objective-C 文件,所以 Swift 可以直接与之对话。您必须注意不要间接地将任何 C + +-ish 文件导入到与 Swift 交互的头文件中。

项目在这里: https://github.com/foundry/OpenCVSwiftStitch

我编写了一个简单的 Xcode 6项目,展示了如何混合 C + + 、 Objective C 和 Swift 代码:

Https://github.com/romitagl/shared/tree/master/c-objc-swift/performance_console

特别是这个例子从 Swift 调用 Objective C 和 C + + 函数。

关键是创建一个共享的 Header Project-Bridge-Header. h,并将 Objective C Header 放在那里。

请下载该项目作为一个完整的例子。

下面是我尝试使用 clang 工具来自动化 C + +/迅速通信。你可以从 swift 中实例化 C + + 类,从 C + + 类继承,甚至在 swift 中重写虚方法。
它将解析您想要导出的 C + + 类,并自动生成 Objective-C/Objective-C + + 桥。

Https://github.com/sandym/swiftpp

我还有一个快速结合 opencv 的演示程序。

你可以从 https://github.com/russj/swift_opencv3_demo下载。

关于演示 http://flopalm.com/opencv-with-swift/的更多信息。

没有,一个都没有。

但是,您可以在 Swift 项目中使用 C + + ,而不需要静态库或框架。正如其他人所说,关键在于创建一个 Objective-C 桥接头,其中 # 包含与 C 兼容的 C + + 头,这些头被标记为与 外部“ C”{}技巧相兼容的 C。

视频教程: https://www.youtube.com/watch?v=0x6JbiphNS4

您还可以在两者之间建立 跳过 Objective-C文件。只需添加一个 C 头文件。Cpp 源文件。在头文件中只有 C 声明,并在源文件中包含任何 C + + 代码。然后将 C 头文件包含在 * *-Bridge-Header.h 中。

下面的示例返回一个指向 C + + 对象(struct Foo)的指针,这样 Swift 就可以存储在 COpaquePointer 中,而不必在全局空间中定义 struct Foo。

H 文件(由 Swift 看到-包含在桥接文件中)

#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

内部源文件 Foo.cpp (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;
}

这种困惑可能来自于这样一种假设,即仅仅将文件扩展名从 .m更改为 .mm就可以在语言之间建立桥梁,而实际上,它并没有这样做。与 .cpp产生摩擦的不是 .mm,而是 .h的头部,它肯定不是 C++的头部。


同一个项目: 是的。

一样项目中,您可以愉快地混合 CC + + 目标 C目标 C + + 斯威夫特,甚至 集合

  1. ...Bridging-Header.h: 使用这个桥将 C目标 C目标-C + + 暴露给 斯威夫特
  2. 暴露 自然而然地你的 斯威夫特类标记为 @objc目标 C
  3. 这是棘手的部分,因为他们含糊不清地用于所有口味的 C++或不,目的或不。如果 .h不包含单个 C + + 关键字(如 class) ,则可以将其添加到 ...Bridging-Header.h中,并将公开它声明的相应 .c .h0 .cpp功能的任何函数。否则,该头必须包装在纯 C.h2API 中。

同样的文件,没有。

一样文件中,你不能把5个都混合在一起。在同一个 源文件中:

  1. 你把 不行和任何东西混合在一起
  2. 你可以把 目标 CC混合
  3. 你可以把 目标 CC + + 混合。这个桥是 目标-C + + 。(@ Vinzzz)。
  4. C
  5. 你可以混合 C + + 集合(@ Vality)
  6. .h: CC + + 目标 C或者 目标-C + + 无处不在而且模棱两可,所以答案是 看情况了。

参考文献

如果这对任何人都有帮助,我还有一个简短的教程,介绍如何从一个简单的 Swift 命令行实用程序调用一个简单的 C + + 静态库。这是一段代码概念的基本证明。

没有涉及 Objective-C,只有 Swift 和 C + + 。C + + 库中的代码由实现具有外部“ C”链接的函数的 C + + 包装器调用。然后在桥接头中引用该函数,并从 Swift 调用该函数。

参见 http://www.swiftprogrammer.info/swift_call_cpp.html

我在官方资源中提供了一个到 SE-0038的链接,描述如下 这保留了对 Swift 编程语言进行更改和用户可见性增强的建议

目前的状态是,这是已被接受但尚未安排的特性请求。

这个链接旨在引导任何寻找这个特性的人朝着正确的方向前进

其他的答案有些不准确。您实际上可以在同一个文件中混合 Swift 和[ Objective-] C [ + + ] ,尽管不是您所期望的那样。

这个文件(c.swift)编译成同时包含 swiftc c.swiftclang -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;
}
// */

(许多技巧中的)一个是

桥接 obj-c + + 文件需要一个 分开头文件..。

您不能像通常那样在同一个. mm 文件中抛出@interface 和@实现。

因此,在桥接头文件中,您有

#import "Linkage.hpp"

Hpp 的@接口用于 Linkage,而 Linkage.mm 的@实现用于. mm

然后

... 你实际上 不要 # 包括“ yourCpp.hpp”在 Linkage.hpp。

只在 Linkage.mm 文件中放入 #include "yourCpp.hpp",在 Linkage.hpp 文件中放入 没有

在许多在线示例/教程中,编写者只是将@接口和@实现放在一起。毫米文件,因为人们经常这样做。

这将在非常简单的 cpp 桥接示例中工作,但是,

问题是:

如果 yourCpp.hpp 具有任何 c + + 特性(比如第一行 #include <something>) ,那么进程就会失败。

但是,如果你只有 不要#include "yourCpp.hpp"在链接 < strong > header 文件(它的罚款有它在。Mm 文件,显然你需要)-它工作。

不幸的是,这只是整个过程中的一个提示。