Swift has some experimental ability to interoperate with C++. This document provides an overview of the status of the Swift and C++ interoperability support.
Swift has the experimental ability to import a large subset of C++. This section of the document describes which C++ language and standard library features can be imported and used from Swift in an experimental manner.
The following example demonstrates several interop features. It compiles and runs on main.
// cxx-types.h (mapped to CxxTypes module in module.modulemap)
#include <algorithm>
#include <vector>
using V = std::vector<long>;
// main.swift
import CxxTypes
import CxxStdlib
// We can extend C++ types in Swift.
extension V : RandomAccessCollection {
public var startIndex: Int { 0 }
public var endIndex: Int { size() }
}
// Create a vector with some data.
var numbers = V(4)
std.fill(numbers.beginMutating(), numbers.endMutating(), 41)
// Transform it using C++.
std.transform(numbers.beginMutating(), numbers.endMutating(),
numbers.beginMutating()) { (element: Int) in
return element + 1
}
// Loop over it in Swift.
for (index, element) in numbers.enumerated() {
print("v[\(index)] = \(element)")
}
// We can also use anything in RandomAccessCollection, such as map and zip.
let strings = numbers.map { "\($0)" }
for (s, n) in zip(strings, numbers) {
print("\(s) = \(n)")
}
There are currently two experimental ways to import C++ into Swift:
- Clang modules: can be imported into Swift. This requires a module map.
- Bridging header: can be imported into Swift. Headers included in the bridging header will be imported. Please note that support for importing C++ 20 modules isn’t implemented.
Both CMake and the Swift package manager can be configured to invoke Swift with the correct arguments to import C++ headers.
Note: C++ code is imported using the Objective-C++ language mode on Apple platforms.
This status table describes which of the following C++ language features can be used in Swift:
C++ Language Feature | Implemented Experimental Support For Using It In Swift |
---|---|
Top-level functions | Yes |
Enumerations | Yes. That includes enum class |
Struct / Class types | Yes - as value types, except for types without a copy constructor. Partial experimental support for importing a C++ struct/class as a reference type |
Typedefs / Type aliases | Yes |
Global Variables | Yes |
Namespaces | Yes |
Inline Namespaces | Yes, with some known issues (#58217) |
Exceptions | No. Uncaught exceptions that propagate into Swift frames are UB. |
Fields | Yes |
Member functions | Yes. Some value category overloads aren't imported |
Virtual Member Functions | No |
Operators | Yes, with some known issues |
Subscript Operators | Yes |
Constructors | Yes. That includes implicit constructors |
Destructor | Yes. C++ destructors are invoked automatically when the value is no longer used in Swift |
Copy constructor / copy assignment operator | Yes. Swift invokes the underlying copy constructor when copying a C++ value |
Move constructor / move assignment operator | No |
Base class member functions / operators | Yes, with some known issues |
Function templates | Yes |
Class templates | Yes |
Dependent types | Partially: imported as Any |
Availability Attributes | Yes |
The following C++ code patterns or language features have specific mappings to Swift language features when imported in Swift:
C++ Language Feature | Imported Into Swift |
---|---|
get /set member functions |
Imported as computed property (starting from Swift-5.7) |
const /non-const member function overload set |
Both overloads are imported as a method, with non-const method being renamed to mutating… (starting from Swift-5.7). The renaming logic will change in a future version of Swift, and non-const methods won't be renamed |
Unless stated otherwise (i.e., imported reference types) all Swift features work with imported types. For example: use in generic contexts, protocol conformance, extensions, etc.
Parts of libc++ can be imported and used from Swift. C++ standard library types are bridged directly to Swift, and there is not automatic bridging to native Swift types. This means that if an imported C++ API returns std::string
, you will get a std::string
value in Swift as well, and not Swift's String
.
This status table describes which of the following C++ standard library features have some experimental support for using them in Swift. Please note that this is not a comprehensive list and other libc++ APIs that use the above supported C++ language features could be imported into Swift.
C++ Standard Library Feature | Can Be Used From Swift |
---|---|
std::string |
Yes |
std::vector |
Yes |
- #58217: Swift's typechecker currently doesn't allow calling a function from an inline namespace when it's referenced through the parent namespace. Example of a test that fails: https://github.com/swiftlang/swift/blob/main/test/Interop/Cxx/namespace/inline-namespace-function-call-broken.swift
This section of the document describes which Swift language and standard library features can be imported and used from C++.
Swift has some experimental support for generating a header that can be imported by C++.
This status table describes which of the following Swift language features have some experimental support for using them in C++.
Functions
Swift functions can be called from C++, with some restrictions. See this table for details:
Swift Language Feature | Implemented Experimental Support For Using It In C++ |
---|---|
Top-level @_cdecl functions |
Yes |
Top-level Swift functions | Yes |
Swift Methods | Yes (see the Methods section below for more details) |
Primitive parameter or result types | Yes |
Swift struct /enum /class parameter or result types |
Yes |
inout parameters |
Yes |
C++ struct /class parameter or result types |
Yes |
Objective-C @interface parameter or result types |
Yes |
Swift closure parameter or result types | No |
Swift protocol type parameter or result types | No |
SIMD type parameter or result types | No |
Variadic parameters | No |
Multiple return values | No |
Structs
Swift Language Feature | Implemented Experimental Support For Using It In C++ |
---|---|
Fixed layout structs | Yes |
Resilient / opaque structs | Yes |
Copy and destroy semantics | Yes |
Initializers | Yes (except for throwing initializers) |
Enums
Swift Language Feature | Implemented Experimental Support For Using It In C++ |
---|---|
Fixed layout enums | Yes |
Resilient / opaque enums | Yes |
Copy and destroy semantics | Yes |
Creation | Yes |
Enums with associated values | Partially: only support structs and enums |
Enums with raw values | Yes |
Indirect enums | No |
Class types
Swift Language Feature | Implemented Experimental Support For Using It In C++ |
---|---|
Class reference values | Yes |
ARC semantics | Yes (C++ copy constructor,assignment operator, destructor perform ARC operations) |
Initializers | Yes (except for throwing initializers) |
Methods
Swift Language Feature | Implemented Experimental Support For Using It In C++ |
---|---|
Instance methods | Yes on structs and enums. Instance methods on class types are partially supported (virtual calls won't be virtual due to a bug right now) |
Static methods | No |
Properties
Swift Language Feature | Implemented Experimental Support For Using It In C++ |
---|---|
Getter accessors | Yes, via get<name> . Boolean properties that start with is or has are remapped directly to a getter method using their original name |
Setter accessors | Yes, via set<name> |
Mutation accessors | No |
Static property accessors | Yes |
Generics
Swift Language Feature | Implemented Experimental Support For Using It In C++ |
---|---|
Generic functions | Partially, only without generic constraints |
Generic methods | Partially, only without generic constraints |
Generic struct types |
Partially, only without generic constraints and less than 4 generic parameters |
Generic enum types |
Partially, only without generic constraints and less than 4 generic parameters |
Generic class types |
No |
This status table describes which of the following Swift standard library APIs have some experimental support for using them in C++.
Swift Library Type | Can be used from C++ |
---|---|
String |
Can be used as a type in C++. APIs in extensions are not exposed to C++. Conversion between std.string is not yet supported |
Array<T> |
Can be used as a type in C++. Ranged for loops are supported. Limited set of APIs in some extensions are exposed to C++. |
Optional<T> |
Can be used as a type in C++. Can be constructed. get extracts the optional value and it's also implicitly castable to bool . |