Home > Software design >  Swift vs C Bridge Enumeration Internals and Metadata
Swift vs C Bridge Enumeration Internals and Metadata

Time:01-03

Question:

Why aren't the outputs the same for what are basically the same enumeration? Does Swift strip metadata from C (I assume it is stripped by the Compiler, then provided again by the Swift Interface File as though it is a normal Swift enum)?

Details:

I have two similar enumerations, one defined in C and one defined in Swift.

However I'm getting different print results, specifically the Swift Enum is able to print the key as a representational String (in this case first), but the C Enum is only able to print the Enumeration name (in this case CNames).

This is the output of the program,

Enumerations in Swift and C
Running on Swift 5
CNames is 1
first is 1
Program ended with exit code: 0

I assume the Swift main file is using the Swift Generated Interface.

  1. This is what my project looks like:

    Project Hierarchy showing all four files in TestAppMain Group in TestApp Project
  2. Here's my native Swift enum, `SNames:

    //
    //  SNames.swift
    //  TestAppMain
    //
    
    import Foundation
    
    public enum SNames : UInt {
        case unknown = 0
        case first = 1
        case middle = 2
        case last = 3
    }
    
  3. Here is my C enum, CNames:

    #ifndef Names_h
    #define Names_h
    
    // NSUInteger type definition
    #import <Foundation/NSObjCRuntime.h>
    
    typedef NS_ENUM(NSUInteger, CNames) {
        NameUnknown = 0,
        NameFirst   = 1,
        NameMiddle  = 2,
        NameLast    = 3,
    };
    
    #endif /* Names_h */
    
  4. Here's the generated Swift 5 Interface:

    // NSUInteger type definition
    import Foundation.NSObjCRuntime
    
    public enum CNames : UInt {
        case unknown = 0
        case first = 1
        case middle = 2
        case last = 3
    }
    
  5. Here is my bridging header:

    #ifndef TestAppMain_Bridging_Header_h
    #define TestAppMain_Bridging_Header_h
    
    #import "CNames.h"
    
    #endif /* TestAppMain_Bridging_Header_h */
    
  6. Finally my main.swift is:

    print("Enumerations in Swift and C")
    #if swift(>=5)
        print("Running on Swift 5")
    #endif
    
    let cFirst = CNames.first
    let sFirst = SNames.first
    
    // Swift Enum is able to output the specific
    // case (i.e first) whereas the C Enum
    // doesn't seem to have that info
    // CNames is 1
    print("\(cFirst) is \(cFirst.rawValue)")
    // first is 1
    print("\(sFirst) is \(sFirst.rawValue)")
    

CodePudding user response:

This is just a limitation of C. C enums are nothing more than a visually grouped set of integer constants.

You'll notice that you get the same limitations when applying @objc to Swift enums:

enum NativeEnum: Int32 { case i = 123 }
print(NativeEnum.i) // => "i"

@objc enum ExportedEnum: Int32 { case i = 123 }
print(ExportedEnum.i) // => "ExportedEnum"
  • Related