At Ordo One, we recently tried using Swift/C++ interoperability for integrating a third-party library on Linux. I’d like to share some feedback on improvements we’ve noticed, as well as a few unexpected behaviors.
First of all, thank you for the huge effort behind this feature. It’s really impressive that Swift can now work directly with C++—this removes a lot of the pain of building an additional C layer.
Combined with other improvements, this is an uber-super feature.
We were able to successfully integrate a third-party library using this interop.
There are a few key things we’ve run into and worked around, but addressing them would make development much smoother:
-
Pimpl idiom with precompiled libraries
Many precompiled libraries use the pimpl idiom. These classes are not automatically accessible in Swift. I raised this previously in slack and on the swift forum with examples, but didn’t receive feedback. Generally, It feels strange that class types aren’t available while structs are, since from a C++ perspective there isn’t much difference between them. -
Virtual functions requiring overrides
Classes with virtual functions that need to be overridden in client code are a major pain point. Right now I have to wrap all of them and expose a different interface.
Ideally, it would be nice if they are available as non-final classes with `open func` to be able to override them. However I understand that it might be nearly impossible as swift and c++ classes are significantly different. -
Protocols in C++
As a workaround for (2), I tried exposing Swift protocols to C++. Unfortunately, protocols are not yet supported in C++.
It would be very useful if they could be represented as pure virtual classes. -
std::function and Swift closures
Since I couldn’t override C++ classes directly or use Swift protocols in C++, I ended up relying on callbacks with std::function. Initially I hoped this would “just work,” and in a sense it did—but only as pure C functions. This led to the need for additional wrappers and some problems passing references. In the end I used this wrapper with modifications for variadic template arguments.
I also noticed real progress between Swift 6.1 and 6.2—some issues were fixed and new features were added.
-
Swift headers (e.g. MyLib-Swift.h) can now be imported into C++, which previously gave a “file not found” error.
-
Static libraries in bundles are now supported on Linux. In 6.1 this only worked on macOS with XCFs.
-
Some linking errors disappeared between 6.1.0 and 6.1.1. For example, I previously hit errors like
Summary
foo.swift.o:foo.swift.o:function std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_add_ref_copy():(.text._ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE15_M_add_ref_copyEv+0x1a): error: undefined reference to '__gnu_cxx::__atomic_add_dispatch(int*, int)'
Miscellaneous Issues and Nice-to-Haves
-
It would be great to have a more direct way to construct std::optional from Swift. I couldn’t find something like .init(value), but perhaps I missed it.
-
Frequent warnings like: `- warning: 'import_owned' Swift attribute ignored on type 'vector': type is not copyable or destructible [#ClangDeclarationImport]`
-
Direct template support in Swift without requiring aliases.
-
In a project structured as SwiftTarget -> CppTarget -> SwiftExecutable, I wasn’t able to use `#include "SwiftTarget-Swift.h"` inside a C++ header. Including it leads to a compilation error when building the Swift executable:
$ swift build --verbose…/…/Sources/CppTarget/Headers/LibCpp/Test.h:4:10: error: ‘SwiftTarget-Swift.h’ file not found
3 |
4 | #include "SwiftTarget-Swift.h"
5 | `- error: 'SwiftTarget-Swift.h' file not found
Once again, a big thank you to everyone working on this. The progress is impressive, and even with the rough edges, Swift/C++ interoperability already makes a big difference for real-world use cases. I hope this feedback helps guide further improvements.
Happy to elaborate further if something is unclear and/or file issues if it would be helpful for tracking something specific.
There are several links for the related issues that I have seen/created before:
- https://forums.swift.org/t/swift-noncopyable-macro-questions/80142
- https://github.com/swiftlang/swift/issues/83805
- https://github.com/swiftlang/swift/issues/83536 - seems kinda regression in 6.2
- https://github.com/swiftlang/swift/issues/80269 / https://github.com/swiftlang/swift/issues/82783 - also when trying to pass swift closure to std function