Hello, I've tried using C++ interop with examples provided by Chatgpt.
The long and short of it is, it doesn't compile. The .hpp file is treated like it's a C header file. If I try to use the cxx interop flag in Package.swift, it's rejected, but if I don't the compilation fails.
Given the errors, I asked Chatgpt and it said there was a mismatch between the compiler (6.2.4) and the build system (5.6).
SwiftC++/Sources/CxxTarget/include/MyCppClass.hpp:6:1: error: unknown type name 'class' | | class MyCppClass { | `- error: unknown type name 'class'
Hello! What exactly do you mean by "it's rejected"? I put together a tiny example following the guide, and it works for me on Ubuntu 24 with both 5.10.1 and 6.2.4.
I did notice a little oddity, though: if the umbrella header is named <target>.hpp instead of <target>.h, the compiler seems to include all headers from include directory, which causes errors due to duplicated declarations. Could someone more familiar with C++ interoperability answer, whether this is expected?
The main problem with my code was that the Package.swift's first line comment referred to swift-tools-version:5.6 instead of 5.9 or 6.2. I was assuming it was just a comment that would be ignored but that was not the case.
After I got the code working, I found a new issue which is that while integers can pass to Swift just fine, const char pointer and std::string pointer both become optionals e.g.
I had to do the following to obtain a Swift string from a const char*: let cppObject = MyCppClass() let pBuffer = cppObject.sayHello()! let swiftStr = String (cString: pBuffer); print (swiftStr)
C string is essentially a pointer to char (char *), so it is imported into Swift as, well, a pointer to char (Unsafe[Mutable]Pointer<CChar>). It's optional (implicitly unwrapped actually), because nothing stops you from returning NULL/nullptr from C++ side, and in this case, value of pointer at the Swift side will be nil. It's no different from C interop behavior, which has been around for long already. Generally, C++ raw pointers (not to be confused with Swift Unsafe[Mutable]Raw[Buffer]Pointer, "raw" in this context means simply untyped pointer) by default will be imported into Swift as Unsafe[Mutable]Pointer.
C++ std::string is imported as it is, using std.string type at Swift side. It isn't converted automatically, but can be converted explicitly into and from Swift.String by one simple call to initializer.
The reference guide is worth reading through; it covers such topics in detail.