我可以将 Swift 与 C++ 混合使用吗?像 Objective-C .mm 文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24042774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I mix Swift with C++? Like the Objective-C .mm files
提问by EhTd
I just changed my .m files to .mm and use C++. Is there a way to do the same with Swift?
我只是将我的 .m 文件更改为 .mm 并使用 C++。有没有办法对 Swift 做同样的事情?
采纳答案by Rob Napier
No. When you switch from .m to .mm you are actually switching from Objective-C to a different language (which has many subtle differences) called Objective-C++. So you're not really using C++; you're using Objective-C++ which accepts most C++ as input (in the same way that C++ accepts most but not all C as input). When I say it's not quite C++, consider a C++ file that includes a variable named nil
(which is legal C++) and then try to compile that as Objective-C++.
不。当您从 .m 切换到 .mm 时,您实际上是从 Objective-C 切换到一种称为 Objective-C++ 的不同语言(有许多细微的差异)。所以你并没有真正使用 C++;您正在使用 Objective-C++,它接受大多数 C++ 作为输入(与 C++ 接受大多数但不是所有 C 作为输入的方式相同)。当我说它不完全是 C++ 时,请考虑一个包含名为变量nil
(这是合法的 C++)的 C++ 文件,然后尝试将其编译为 Objective-C++。
Swift doesn't have the same relationship. It is not a superset of C or C++, and you can't directly use either in a .swift
file.
Swift 没有相同的关系。它不是 C 或 C++ 的超集,您不能直接在.swift
文件中使用。
"Using Swift with Cocoa and Objective-C"also tells us:
《将 Swift 与 Cocoa 和 Objective-C 一起使用》也告诉我们:
You cannot import C++ code directly into Swift. Instead, create an Objective-C or C wrapper for C++ code.
您不能将 C++ 代码直接导入 Swift。相反,为 C++ 代码创建一个 Objective-C 或 C 包装器。
回答by SwiftArchitect
The confusion may come from the assumption that merely changing a file extension from .m
to .mm
is all you need to bridge the languages, when, in reality, it does nothing of that sort. It is not the .mm
that causes friction with .cpp
, it is the .h
header which must positively not be a C++
header.
这种混乱可能来自于假设,即只改变从文件扩展名.m
来.mm
是所有你需要弥合语言的时候,在现实中,它什么也不做那种。与.mm
产生摩擦的不是.cpp
,而是.h
头球必须肯定不是C++
头球。
Same project: Yes.
同一个项目:是的。
In the sameproject, you can happily mix C, C++, Objective-C, Objective C++, Swift, and even Assembly.
在同一个项目中,你可以愉快地混合使用C、C++、Objective-C、Objective C++、Swift,甚至是Assembly。
...Bridging-Header.h
: you expose C, Objective-Cand Objective-C++to Swiftusing this bridge<ProductModuleName>-Swift.h
: exposes automaticallyyour Swiftclasses marked with@objc
to Objective-C.h
: this is the tricky part, since they are ambiguously used for all flavors of C, ++or not, Objectiveor not. When a.h
does not contain a single C++keyword, likeclass
, 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 Cor Objective-CAPI.
...Bridging-Header.h
:您使用此桥将C、Objective-C和Objective-C++公开给Swift<ProductModuleName>-Swift.h
:自动向Objective-C公开你标记的Swift类@objc
.h
:这是棘手的部分,因为它们被含糊不清地用于所有类型的C,++与否,Objective与否。当 a.h
不包含单个C++关键字时,例如class
,可以将其添加到 中...Bridging-Header.h
,并将公开其声明的相应函数.c
或.cpp
功能。否则,该标头必须包含在纯C或Objective-CAPI 中。
Same file: No.
同一个文件:没有。
In the samefile, you can't mix all 5. In the same source file:
在同一个文件中,你不能混合所有 5. 在同一个源文件中:
.swift
: you can'tmix Swiftwith anything.m
: you can mix Objective-Cwith C. (@Vinzzz).mm
: you can mix Objective-Cwith C++. This bridge is Objective-C++. (@Vinzzz)..c
: pure C.cpp
: you can mix C++& Assembly(@Vality).h
: ubiquitous and ambiguous C, C++, Objective-Cor Objective-C++, so the answer is it depends.
.swift
: 你不能把Swift和任何东西混在一起.m
:您可以将Objective-C与C混合使用。( @Vinzzz).mm
:您可以将Objective-C与C++混合使用。这座桥是Objective-C++。(@Vinzzz)。.c
:纯C.cpp
:您可以混合使用C++和汇编(@Vality).h
:无处不在和模棱两可的C、C++、Objective-C或Objective-C++,所以答案取决于它。
References
参考
- Invoke Assembly from C++(Brett Hale)
- Invoke Swift from Objective-C(Svitlana)
- Invoke C, C++, Obj-C, Obj-C++ from Swift(SwiftArchitect, self)
- To download a full iOS 9, Xcode 7 project, search for SO-32541268in Swift Recipes.
- 从 C++ 调用程序集(Brett Hale)
- 从 Objective-C 调用 Swift( Svitlana)
- 从 Swift 调用 C、C++、Obj-C、Obj-C++(SwiftArchitect,self)
- 要下载完整的 iOS 9、Xcode 7 项目,请在 Swift Recipes 中搜索SO-32541268。
回答by Gian Luigi Romita
I wrote a simple Xcode 6 project that show how to mix C++, Objective C and Swift code:
我编写了一个简单的 Xcode 6 项目,展示了如何混合 C++、Objective C 和 Swift 代码:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
In particular the example call an Objective C and a C++ function from the Swift.
特别是该示例从 Swift 调用了一个 Objective C 和一个 C++ 函数。
The key is to create a shared header Project-Bridging-Header.h and put the Objective C headers there.
关键是创建一个共享头文件 Project-Bridging-Header.h 并将目标 C 头文件放在那里。
Please download the project as a complete example.
请下载该项目作为完整示例。
回答by Dan G
You can also skip the Objective-Cfile in between. Just add a C header file with a .cpp source file. Have only C declarations in the header file and include any C++ code in the source file. Then include the C header file in the **-Bridging-Header.h.
您也可以跳过其间的 Objective-C文件。只需添加一个带有 .cpp 源文件的 C 头文件。在头文件中只有 C 声明,并且在源文件中包含任何 C++ 代码。然后在 **-Bridging-Header.h 中包含 C 头文件。
The following example returns a pointer to a C++ object (struct Foo) so Swift can store in a COpaquePointer instead of having struct Foo defined in the global space.
下面的示例返回一个指向 C++ 对象 (struct Foo) 的指针,因此 Swift 可以存储在 COpaquePointer 中,而不是在全局空间中定义 struct Foo。
Foo.h file (seen by Swift - included in the bridging file)
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
Inside source file Foo.cpp (not seen by Swift):
内部源文件 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;
}
回答by foundry
I have just made a little example project using Swift, Objective-C and C++. It's a demo of how to use OpenCV stitching in iOS. The OpenCV API is C++ so we can't talk to it directly from Swift. I use a small wrapper class who's implementation file is Objective-C++. The Headerfile is clean Objective-C, so Swift can talk to this directly. You have to take care not to indirectly import any C++-ish files into the the headers that Swift interacts with.
我刚刚使用 Swift、Objective-C 和 C++ 制作了一个小示例项目。这是一个如何在 iOS 中使用 OpenCV 拼接的演示。OpenCV API 是 C++,所以我们不能直接从 Swift 与它对话。我使用一个小的包装类,它的实现文件是 Objective-C++。该头文件是干净的Objective-C,所以雨燕进行直接通话这一点。您必须注意不要将任何 C++-ish 文件间接导入 Swift 与之交互的头文件中。
The project is here: https://github.com/foundry/OpenCVSwiftStitch
回答by Sandy
Here's my attempt at a clang tool to automate C++/swift communication. You can instanciate C++ classes from swift, inherit from C++ class and even override virtual methods in swift.
It will parse the C++ class you want to export to swift and generate the Objective-C/Objective-C++ bridge automatically.
这是我尝试使用 clang 工具来自动化 C++/swift 通信。您可以从 swift 实例化 C++ 类,从 C++ 类继承,甚至在 swift 中覆盖虚拟方法。
它将解析您要导出到 swift 的 C++ 类并自动生成 Objective-C/Objective-C++ 桥。
回答by Austin
Swift is not directly compatible with C++. You can work around the issue by wrapping your C++ code with Objective-C, and using the Objective C wrapper in Swift.
Swift 与 C++ 不直接兼容。您可以通过使用 Objective-C 包装 C++ 代码并在 Swift 中使用 Objective C 包装器来解决此问题。
回答by Russj
I also have a demo program for swift combining opencv.
我也有一个快速结合opencv的演示程序。
You can download it from https://github.com/russj/swift_opencv3_demo.
你可以从https://github.com/russj/swift_opencv3_demo下载它。
More information about the demo http://flopalm.com/opencv-with-swift/.
回答by James Mart
No, not in a single file.
不,不是在单个文件中。
However, you may use C++ in Swift Projects without needing a static library or framework. Like others have said, the key is to make an Objective-C bridging header that #includes C-compatible C++ headers that are marked as C compatible with the extern "C" {}trick.
但是,您可以在 Swift 项目中使用 C++,而无需静态库或框架。就像其他人所说的那样,关键是制作一个 Objective-C 桥接头文件,其中 #includes C 兼容 C++ 头文件被标记为 C 与extern "C" {}技巧兼容。
Video tutorial: https://www.youtube.com/watch?v=0x6JbiphNS4
回答by snake5
Other answers are slightly inaccurate. You can actually mix both Swift and [Objective-]C[++] in the same file, though not quite the way you would expect.
其他答案有点不准确。实际上,您可以在同一个文件中混合使用 Swift 和 [Objective-]C[++],尽管与您期望的方式不太一样。
This file (c.swift) compiles to a valid executable with both swiftc c.swift
and clang -x objective-c c.swift
此文件(c.swift)编译成既具有有效的可执行swiftc c.swift
和clang -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;
}
// */