2014-12-29 5 views
8

कोर मिडी एक सी एपीआई है जो क्षमताओं को कहीं और नहीं मिलती है।स्विफ्ट में "डाउनकास्टिंग" सी स्ट्रक्चर

जब उपयोगकर्ता का MIDI सेटअप बदलता है (उदा। आप किसी डिवाइस में प्लग इन होते हैं), तो एक सूचना होती है।

यह फ़ंक्शन का प्रकार है जिसे कहा जाता है।

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 MIDINotification { 
    var messageID: MIDINotificationMessageID 
    var messageSize: UInt32 
} 

आप इस तरह कॉलबैक लागू हो सकता है:

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

पहले पैरामीटर एक MIDINotification struct जो इस तरह दिखता है आपको किस तरह की अधिसूचना मिली है। कई हैं (मैं सिर्फ एक दिखा रहा हूं)। अधिसूचना के प्रत्येक प्रकार के लिए, आप में पारित एक अलग struct मिल जाएगा इस struct जब एक डिवाइस जोड़ा या हटा दिया गया है आप प्राप्त है:।

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

जैसा कि आप देख, इस struct अतिरिक्त जानकारी है। उदाहरण के लिए "बच्चा" डिवाइस के लिए अंत बिंदु हो सकता है, इसलिए आपको इन फ़ील्ड की आवश्यकता है।

समस्या MIDINbjectAddRemoveNotification को MIDINOTification संरचना (कॉलबैक हस्ताक्षर द्वारा आवश्यक) से कास्टिंग कर रही है। जिस पंक्ति को मैंने "as" का उपयोग करके दिखाया है वह काम नहीं करता है।

क्या आपके पास इस तरह के "डाउनकास्टिंग" के लिए कोई सुझाव है?

उत्तर

2

मेरा सुझाव है कि आप मानक-लाइब्रेरी फ़ंक्शन unsafeBitCast देखें।

2

Vatsal Manot suggested के रूप में, MIDINotification और MIDIObjectAddRemoveNotification किसी भी विरासत या अनुबंध से संबंधित नहीं हैं, स्विफ्ट उन संरचनाओं के बीच कोई सुरक्षित कास्टिंग नहीं कर सकता है।

आप स्पष्ट रूप से unsafeBitCast समारोह का उपयोग कर इसे कास्ट करने के लिए की आवश्यकता होगी:

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

ध्यान दें कि यह समारोह हमेशा डाले प्रदर्शन करने के लिए स्विफ्ट में इस्तेमाल किया जा सकता है, लेकिन यह बेहद असुरक्षित है और आप के रूप में केवल यह प्रयोग करना चाहिए अंतिम संभव समाधान।

+0

अपडेट: ठीक है, यह थोड़ी देर के लिए काम करता है। अब यह स्विफ्ट 2.0 बीटा में टूटा हुआ है। –

1

आप एक चीज़ भूल रहे हैं। यहां तक ​​कि यह ओब्जे-सी कास्टिंग हमेशा पॉइंटर्स पर होता है। आप स्मृति में स्मृति को नहीं डाल सकते हैं (ठीक है, कभी-कभी आप इसे दोबारा परिभाषित कर सकते हैं, लेकिन यह बहुत सुरक्षित नहीं है)।

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 
} 
संबंधित मुद्दे