Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
922 views
in Technique[技术] by (71.8m points)

xcode - Swift and comparing C typedef enums

I recently updated to Xcode-Beta4. I'm working with a c api and there is a typedef enum like this:

typedef enum {
    XML_ELEMENT_NODE=       1,
    XML_ATTRIBUTE_NODE=     2,
    ...
} xmlElementType;

Now I have a xml node, which type I want to check. Therefore the right way would be:

if currentNode.memory.type != XML_ELEMENT_NODE {

In Beta 3 I had to replace XML_ELEMENT_NODE with 1. Now this does not work anmyore. In both cases I get the error xmlElementType is not convertible to UInt8

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The simplest workaround is to find the header and replace the typedef enum with an typedef NS_ENUM(...). The problem with this solution is that everybody in your team has to make the changes.

The problem is caused by the fact that the C enum is converted into an opaque type (struct?) C.xmlElementType. This type has one single property value of type UInt32. Unfortunately, this property is not public. You can call it from the debugger but using it in compiled code results in an error.

I managed to do a workaround using reflect but it's a big hack:

extension xmlElementType : Equatable {
}

public func ==(lhs: xmlElementType, rhs: xmlElementType) -> Bool {
    var intValue1 = reflect(lhs)[0].1.value as UInt32
    var intValue2 = reflect(rhs)[0].1.value as UInt32

    return (intValue1 == intValue2)
}

var elementType = currentNode.memory.type

if elementType == xmlElementType(1) {
    println("Test")
}

I think this is a bug. Either the equality should be defined or some way to cast the struct to an integer.

EDIT:

Another option is to add an inline conversion function to your bridging header:

static inline UInt32 xmlElementTypeToInt(xmlElementType type) {
    return (UInt32) type;
}

And then define equality as

public func ==(lhs: xmlElementType, rhs: xmlElementType) -> Bool {
    return ((xmlElementTypeToInt(lhs) == xmlElementTypeToInt(rhs))
}

However, the most simple option I have found is to brutally cast the struct to an UInt32:

public func ==(lhs: xmlElementType, rhs: xmlElementType) -> Bool {
    var leftValue: UInt32 = reinterpretCast(lhs)
    var rightValue: UInt32 = reinterpretCast(rhs)

   return (leftValue == rightValue)
}

Note this is less reliable because you have to make sure that the struct actually has 32 bytes and it is not an UInt8, for example. The C conversion function is more stable.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...