【问题标题】:"Downcasting" C Structs in Swift在 Swift 中“向下转换”C 结构
【发布时间】:2014-12-29 13:48:32
【问题描述】:

Core MIDI 是一个 C API,它提供了其他地方没有的功能。

当用户的 MIDI 设置发生变化时(例如,您插入了设备),会有通知。

这是被调用函数的类型。

typealias MIDINotifyProc = CFunctionPointer<((UnsafePointer<MIDINotification>, UnsafeMutablePointer<Void>) -> Void)>

第一个参数是一个 MIDINotification 结构,如下所示:

struct MIDINotification {
    var messageID: MIDINotificationMessageID
    var messageSize: UInt32
}

你可以这样实现回调:

func MyMIDINotifyProc (np:UnsafePointer<MIDINotification>, refCon:UnsafeMutablePointer<Void>) {        
    var notification = np.memory       
    switch (notification.messageID) {

    case MIDINotificationMessageID(kMIDIMsgObjectAdded):
        // In Objective-C you would just do a cast here
        // This is the problem line
        var m = np.memory as MIDIObjectAddRemoveNotification

您将查看 messageID 成员以了解您刚刚收到的通知类型。有几个(我只展示一个)。对于每种通知,您将获得不同的结构体。这是添加或删除设备时获得的结构体:

struct MIDIObjectAddRemoveNotification { 
    var messageID: MIDINotificationMessageID
    var messageSize: UInt32
    var parent: MIDIObjectRef
    var parentType: MIDIObjectType
    var child: MIDIObjectRef
    var childType: MIDIObjectType
}

如你所见,这个结构有额外的信息。例如,“孩子”可能是设备的端点,因此您需要这些字段。

问题是从 MIDINotification 结构(回调签名要求)转换为 MIDIObjectAddRemoveNotification。我使用“as”显示的行不起作用。

你对这种“低调”有什么建议吗?

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    作为Vatsal Manot suggested,由于MIDINotificationMIDIObjectAddRemoveNotification 没有任何继承或契约相关,Swift 无法在这些结构之间执行任何安全转换。

    您需要使用unsafeBitCast 函数显式转换它:

    case MIDINotificationMessageID(kMIDIMsgObjectAdded):
        let m = unsafeBitCast(np.memory, MIDIObjectAddRemoveNotification.self)
    

    请注意,此函数始终可以在 Swift 中用于执行强制转换,但它非常不安全,您应该仅将其用作最后可能的解决方案。

    【讨论】:

    • 更新:它工作了一段时间。它现在在 Swift 2.0 beta 中被破坏了。
    【解决方案2】:

    我建议你查看标准库函数unsafeBitCast

    【讨论】:

      【解决方案3】:

      你忘记了一件事。即使是 Obj-C,转换也总是发生在指针上。您不能将内存转换为内存(嗯,有时您可以重新解释它,但它不是很安全)。

      let notification = np.memory
      
      switch (notification.messageID) {            
          case MIDINotificationMessageID(kMIDIMsgObjectAdded):
             //cast the pointer!
             let addedNp = UnsafeMutablePointer<MIDIObjectAddRemoveNotification>(np)
             //now you can just access memory directly
             var m = addedNp.memory
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-15
        • 1970-01-01
        • 1970-01-01
        • 2013-06-24
        相关资源
        最近更新 更多