himeshi
(Himeshi)
1
Hi all!
I'm trying the cxx interoperability feature.
I have a Swift file like this.
public class MyClass {
public func speak() {
print("Hello, 334")
}
}
Then, I want to export a module header so that I can use this Swift class from a C++ class. So I executed the following command.
xcrun swiftc -c MyClass.swift -emit-objc-header -module-name MySwiftModule -enable-experimental-cxx-interop
However, the exported module header MySwiftModule.h does not contain MyClass. The exported file ends with the following code.
#if defined(__OBJC__)
#endif
#if defined(__cplusplus)
#endif
#if __has_attribute(external_source_symbol)
# pragma clang attribute pop
#endif
#pragma clang diagnostic pop
#endif
How can I export a Swift class in the module header for C++? Thank you for your help!
(versions)
% xcrun swift -v
Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
Target: arm64-apple-macosx13.0
Alex_L
(Alex Lorenz)
2
At the moment you need to annotate the class with the @_expose(Cxx) attribute, and then it should be added to the generated header:
@_expose(Cxx)
public class MyClass {
This requirement will go away in the very near future.
1 Like
Alex_L
(Alex Lorenz)
3
Also note that Swift 5.7 does not support this functionality. You will want to try this on a Swift-5.8 or main align toolchain downloaded from swift.org.
1 Like
tera
4
If that's a practical need and you need it today – you can call swift from C++ (and back) via Obj-C inter-op (the class would have to be NSObject subclass) or via registering swift callback (either as convention (c) with a C function pointer, or a normal if you can tolerate using "blocks" on the C side). Ask here or privately if you are new to this and want to know details of those alternatives.
himeshi
(Himeshi)
5
Using Swift 5.8 toolchain and adding @_expose(Cxx) made the module header contain the Swift class for C++, and I succeeded in calling a Swift class from a C++ class.
Thank you for your advices!
(Just for those who has visited here)
The Swift file became
@_expose(Cxx)
public class MyClass {
public init() { /* just make it public */ }
public func speak() {
print("Hello, 334")
}
}
The module header generation command is
xcrun --toolchain swift swiftc -c MyClass.swift -emit-objc-header -module-name MySwiftModule -enable-experimental-cxx-interop
And to call the Swift class from a C++ class,
#include "MyCppClass.hpp"
#include "MySwiftModule.h"
void MyCppClass::someFunc() const {
MySwiftModule::MyClass myObj = MySwiftModule::MyClass::init();
myObj.speak();
}
Alex_L
(Alex Lorenz)
6
Great!
An additional side note, in case you run into this: if you try to call an overriden speak function in the subclass of MyClass, the generated C++ header will not do correct a virtual dispatch through the vtable, and will invoke the base speak function instead. I'm working on fixing this right now ([interop][SwiftToCxx] dispatch Swift class methods correctly using th… by hyp · Pull Request #63560 · apple/swift · GitHub).
1 Like