Swift Cpp/c++ interop: swift functions with c++ enums arguments not available in c++

I'm trying to develop a mix-language (c++ and Swift) framework where calls are mainly from c++ -> Swift. However, I'm having problems with get Swift functions available in c++ when they take a c++ enum value as parameter.

Assume the following c++ header:

#pragma once

enum class MyCppEnumClass { A, B, C };
enum class MyCppEnum { D, E, F };

and following Swift source file:

public func swiftFunctionWithCppEnumClass(_ value: MyCppEnumClass) {
  print("Swift function with C++ enum: \(value)")
}

public func swiftFunctionWithCppEnum(_ value: MyCppEnum) {
  print("Swift function with C++ enum: \(value)")
}

The project compiles correctly this way, so the bridging of the enum types does work, making both the enum and enum class available in Swift. However, when inspecting the generated Swift header, I'm seeing this:

namespace CxxInteropExperiments SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("CxxInteropExperiments") {

// Unavailable in C++: Swift global function 'swiftFunctionWithCppEnum(_:)'.

// Unavailable in C++: Swift global function 'swiftFunctionWithCppEnumClass(_:)'.

} // namespace CxxInteropExperiments

I can't find any information on swift.org (https://www.swift.org/documentation/cxx-interop/) that this would be unsupported. Currently the only solution I can find is to 'mirror' the enum with native Swift enum and implement a convert function in c++ like so:

public enum MySwiftEnum {
  case A
  case B
  case C
}

public func swiftFunctionWithSwiftEnum(_ value: MySwiftEnum) {
  print("Swift function with Swift enum: \(value)")
}
#include <CxxInteropExperiments/CxxInteropExperiments-Swift.h>

CxxInteropExperiments::MySwiftEnum convert(MyCppEnumClass e) {
  switch(e) {
    case MyCppEnumClass::A: return CxxInteropExperiments::MySwiftEnum::A();
    case MyCppEnumClass::B: return CxxInteropExperiments::MySwiftEnum::B();
    case MyCppEnumClass::C: return CxxInteropExperiments::MySwiftEnum::C();
  }
}

void callSwiftFunctionWithEnum(MyCppEnumClass e) {
  CxxInteropExperiments::swiftFunctionWithSwiftEnum(convert(e));
}

and not use c++ enum or enum classes in Swift function signatures that I want to be able to use in c++.

Am I missing something obvious, or is passing c++ enum values directly to Swift functions just not possible? Any help is appreciated.

Replies

enum class MyCppEnum { D, E, F };

I think you meant

enum MyCppEnum { D, E, F };

I can’t answer your question though. I think I have used swift enums in C++, but there was something nasty about it; maybe it mangled the names in some way? That’s right, it generated a non-class enum with the enum name prefixed to all the element names.

I think it is safe to cast, rather than needing that switch.

  • Yup, you're right. I meant the second enum to be a regular enum instead of an enum class.

Add a Comment

Using swift enums in C++ isn't an issue, and it indeed does that weird'ish naming for the cases. What bothers me is that the Swift functions that I define that take a C++ enum or enum class just don't get interop at all. If the function is a global function, I get the

// Unavailable in C++: Swift global function 'swiftFunctionWithCppEnum(_:)'.

comment in the generate header. What's worse is that if the function is member for a Swift class, it just gets ommitted entirely without any indication that it is not compatible. It just doesn't show up at all in the generate Swift header.

Upon further reading the C++ interop documentation I came across this:

If I understand it correctly, this indicates that it actually should work? But it clearly doesn't.

This is your Swift Forums thread, right?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • Jup, that’s correct.

Add a Comment