-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[cxx-interop] Using a C++ enum in Swift, cannot be used in C++ anymore (bi-directional Swift <-> C++ code) #75330
Comments
After reading "Exposing Swift APIs to C++", it seems like this should be supported - their example calls a Swift function from C++, which uses a C++ type: So maybe there is something broken with my setup. It's probably worth mentioning that I am using this in a CocoaPods project, so the modulemap is generated automatically. As of right now, the modulemap just exports everything: module react_native_nitro_image {
umbrella header "react-native-nitro-image-umbrella.h"
export *
module * { export * }
} I am not sure why this is not working in this case. |
I tried to reproduce your issue and got the exact same error. First, I tried looking in the build folder, located at public class SomethingSwift {
public var someEnum: SomeEnum { get { return SomeEnum.first } }
public var someInt: Int { get { return 0 } }
public var someStruct: MyStruct { get { return MyStruct(myEnum: .first) } }
} Hence, the issue seems to be happening when using C++ enums in Swift. Very interesting indeed. After some fiddling around, I actually got your code to (sort of) work. My temporary solution is to encapsulate the enum within a struct as below. struct MyStruct {
SomeEnum myEnum;
}; Along with: SomeEnum getSomeEnum() { return _swiftPart.getSomeStruct().myEnum; } In Could you try this and verify that it works for you as well? |
Hey @ludwwwig - thank you for your reply & thank you for reproducing. You are right - wrapping it in a struct works! 🤯 I'll use that workaround for now, I'll try to fiddle with the Swift Compiler here to see if I can find a fix for this - but I'm far from a compiler engineer so I'd have no idea what I'm doing. 🙈 |
Glad to hear that the workaround worked for you, @mrousavy! |
Btw.; another workaround (maybe more efficient? idk) is to just use the enum's |
@mrousavy I find it hard to believe that wrapping of the enum inside a struct would lead to much overhead, if any at all. That being said, your solution is more clear than mine, so I would definitely go with that! 👍🏻 |
I think circular dependencies like this might not be supported but this particular case can be easily factored out so we no longer have circular dependencies. I added a test in this PR: #75685 |
@Xazax-hun Hi, I cherry-picked your test and tried running it with the
I am currently building the Update: The test passes on |
Description
I'm creating a C++ class that has a Swift implementation.
Since Swift doesn't support inheriting from C++ classes (yet), I have to write the methods twice, and just add the Swift instance as a member to the C++ instance:
The problem here now is that Swift depends on the C++ code (
SomeEnum
), and C++ depends on the Swift code (SomethingSwift
) - so it is a cyclic include.I tried separating this out into multiple files, but no luck - Swift generates a single C++ header (
MyLibrary-Swift.h
), and if at any point I try to depend on C++ <-> Swift, it breaks the build with errors like these:- No member named 'getSomething' in 'MyLibrary::SomethingSwift'
If I just return an
Int
instead ofSomeEnum
it works fine, so it is definitely theSomeEnum
part that breaks.Reproduction
Expected behavior
I expect Swift to properly resolve the C++ types and break up cyclic includes by either forward declaring it or just splitting the headers.
Environment
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
Additional information
No response
The text was updated successfully, but these errors were encountered: