Swift中的“向下倾斜”C结构
Core MIDI是一种C API,提供其他地方没有的function。
当用户的MIDI设置发生变化时(例如,您插入了设备),会有通知。
这是被调用的函数的类型。
typealias MIDINotifyProc = CFunctionPointer<((UnsafePointer, UnsafeMutablePointer) -> Void)>
第一个参数是MIDINotification结构,如下所示:
struct MIDINotification { var messageID: MIDINotificationMessageID var messageSize: UInt32 }
您可以像这样实现回调:
func MyMIDINotifyProc (np:UnsafePointer, refCon:UnsafeMutablePointer) { 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 }
如您所见,此结构具有其他信息。 例如,“child”可能是设备的端点,因此您需要这些字段。
问题是从MIDINotification结构(回调签名所需)转换为MIDIObjectAddRemoveNotification。 我使用“as”显示的行不起作用。
你对这种“向下转型”有什么建议吗?
正如Vatsal Manot所说 ,由于MIDINotification
和MIDIObjectAddRemoveNotification
与任何inheritance或契约无关,因此Swift无法在这些结构之间执行任何安全转换。
你需要使用unsafeBitCast
函数显式地unsafeBitCast
它:
case MIDINotificationMessageID(kMIDIMsgObjectAdded): let m = unsafeBitCast(np.memory, MIDIObjectAddRemoveNotification.self)
请注意,此函数始终可以在Swift中用于执行强制转换,但它非常不安全,您应该仅将其用作最后一种可能的解决方案。
我建议你研究标准库函数unsafeBitCast
。
你忘记了一件事。 即使是Obj-C,铸造总是发生在指针上。 你不能把记忆存储到记忆中(好吧,有时你可以,重新解释它,但它不是很安全)。
let notification = np.memory switch (notification.messageID) { case MIDINotificationMessageID(kMIDIMsgObjectAdded): //cast the pointer! let addedNp = UnsafeMutablePointer(np) //now you can just access memory directly var m = addedNp.memory }