2016-07-08 141 views
0

我希望有人可以帮助我使用Xcode 8和Swift 3 我有一个操作系统文件Xcode 7 swift 2涉及Midi的Midi回调输入一切正常罚款7Swift 2到Swift 3转换Midi输入

我试过转换为8,它提出了关于内存的错误和几个名称的变化,主要是我认为是非认真的我也重新定义了使用PlaygroundSupport的无限循环 但是,我无法获得的错误涉及MyMIDIReadProc在

MIDIInputPortCreate(midiClient, "MidiTest_InPort", MyMIDIReadProc, nil, &inPort); 

错误说 无法将类型'(pktList:UnsafePointer,readProcRefCon:UnsafeMutablePointer,srcConnRefCon:UnsafeMutablePointer) - > Void'转换为期望的参数类型'MIDIReadProc'(aka'@convention(c)(UnsafePointer,Optional>,Optional>) - >' ()')

我的理解是,它需要一个@convention(c)插入一些描述的包装。我认为我在正确的轨道上,因为你可以包装一个功能,但我知道把它放在哪里已经用完了。再次,我希望有一个人也许能提醒

感谢您阅读 道歉任何脏话,因为我自学

这里原来的Xcode 7码

  import Cocoa 
      import CoreMIDI 
      import XCPlayground 

      func getDisplayName(obj: MIDIObjectRef) -> String 
      { 
       var param: Unmanaged<CFString>? 
       var name: String = "Error"; 

       let err: OSStatus = MIDIObjectGetStringProperty(obj, kMIDIPropertyDisplayName, &param) 
       if err == OSStatus(noErr) 
       { 
        name = param!.takeRetainedValue() as String 
       } 

       return name; 
      } 

      func MyMIDIReadProc(pktList: UnsafePointer<MIDIPacketList>, 
       readProcRefCon: UnsafeMutablePointer<Void>, srcConnRefCon: UnsafeMutablePointer<Void>) -> Void 
      { 
       let packetList:MIDIPacketList = pktList.memory; 
       let srcRef:MIDIEndpointRef = UnsafeMutablePointer<MIDIEndpointRef>(COpaquePointer(srcConnRefCon)).memory; 
       print("MIDI Received From Source: \(getDisplayName(srcRef))"); 

       var packet:MIDIPacket = packetList.packet; 
       for _ in 1...packetList.numPackets 
       { 
        let bytes = Mirror(reflecting: packet.data).children; 
        var dumpStr = ""; 
        // bytes mirror contains all the zero values in the ridiulous packet data tuple 
        // so use the packet length to iterate. 
        var i = packet.length; 
        for (_, attr) in bytes.enumerate() 
        { 
         dumpStr += String(format:"$%02X ", attr.value as! UInt8); 
         --i; 
         if (i <= 0) 
         { 
          break; 
         } 
        } 

        print(dumpStr) 
        packet = MIDIPacketNext(&packet).memory; 
       } 
      } 

      var midiClient: MIDIClientRef = 0; 
      var inPort:MIDIPortRef = 0; 
      var src:MIDIEndpointRef = MIDIGetSource(0); 

      MIDIClientCreate("MidiTestClient", nil, nil, &midiClient); 
      MIDIInputPortCreate(midiClient, "MidiTest_InPort", MyMIDIReadProc, nil, &inPort); 

      MIDIPortConnectSource(inPort, src, &src); 

      // Keep playground running 
      XCPlaygroundPage.currentPage.needsIndefiniteExecution = true; 

这里是Xcode 8代码转换

  var str = "Hello, playground" 
      import Cocoa 
      import CoreMIDI 
      import XCPlayground 
      import PlaygroundSupport 


      func getDisplayName(obj: MIDIObjectRef) -> String 
      { 
      var param: Unmanaged<CFString>? 
      var name: String = "Error"; 

      let err: OSStatus = MIDIObjectGetStringProperty(obj, kMIDIPropertyDisplayName, &param) 
      if err == OSStatus(noErr) 
      { 
      name = param!.takeRetainedValue() as String 
      } 

      return name; 
      } 


      func MyMIDIReadProc(pktList: UnsafePointer<MIDIPacketList>, 
           readProcRefCon: UnsafeMutablePointer<Void>, srcConnRefCon: UnsafeMutablePointer<Void>) -> Void 
      { 


      let packetList:MIDIPacketList = pktList.pointee; 

      let srcRef:MIDIEndpointRef = UnsafeMutablePointer<MIDIEndpointRef>(OpaquePointer(srcConnRefCon)).pointee; 
      print("MIDI Received From Source: \(getDisplayName(obj: srcRef))"); 

      var packet:MIDIPacket = packetList.packet; 
      for _ in 1...packetList.numPackets 
      { 
      let bytes = Mirror(reflecting: packet.data).children; 
      var dumpStr = ""; 

      var i = packet.length; 
      for (_, attr) in bytes.enumerated() 
      { 
      dumpStr += String(format:"$%02X ", attr.value as! UInt8); 
      i -= 1; 
      if (i <= 0) 
      { 
      break; 
      } 

      } 

      print(dumpStr) 
      packet = MIDIPacketNext(&packet).pointee; 
      } 
      } 

      var midiClient: MIDIClientRef = 0; 
      var inPort:MIDIPortRef = 0; 
      var src:MIDIEndpointRef = MIDIGetSource(0); 

      MIDIClientCreate("MidiTestClient", nil, nil, &midiClient); 

      MIDIInputPortCreate(midiClient, "MidiTest_InPort", MyMIDIReadProc, nil, &inPort); 

      MIDIPortConnectSource(inPort, src, &src); 


      PlaygroundPage.current.needsIndefiniteExecution = true 

回答

1

指针类型在夫特急剧变化3.许多基于C语言的API的签名被相应地改变。

手动执行这些更改会很痛苦。你可以让Swift为你工作,稍作修改。

尝试改变函数头:

func MyMIDIReadProc(pktList: UnsafePointer<MIDIPacketList>, 
           readProcRefCon: UnsafeMutablePointer<Void>, srcConnRefCon: UnsafeMutablePointer<Void>) -> Void 
      { 

到闭合声明:

let MyMIDIReadProc: MIDIReadProc = {pktList, readProcRefCon, srcConnRefCon in 

雨燕完美推断参数类型的这种风格。

您可能需要修复的指针类型转换:

let srcRef:MIDIEndpointRef = UnsafeMutablePointer<MIDIEndpointRef>(OpaquePointer(srcConnRefCon)).pointee; 

到这样的事情:

//I'm not sure using `!` is safe here... 
    let srcRef: MIDIEndpointRef = UnsafeMutablePointer(srcConnRefCon!).pointee 

(顺便说一下,在您的Xcode 7码相当于一部分是有点多余你有没有必要使用中间COpaquePointer那里。)


在斯威夫特3,三分球不能为零,可为空的指针用Optionals表示。您可能需要许多其他修补程序才能在Swift 3中使用基于C的API。

0

OOPer正指向(ahem)您处于正确的方向。这里是一篇关于使用Swift 3 Core MIDI以及一个可用的github回购的博客文章。

0

假设您正在使用CoreMIDI 1.3或更高版本,使用MIDIInputPortCreateWithBlock而不是MIDIInputPortCreate可能会带来更多运气。

此方法需要一个夫特块作为一个参数的,而不是要求一个@convention(c)功能参考,使之更适合于属于夫特类的方法中使用,例如:

public func midiReadBlock(ptr: UnsafePointer<MIDIPacketList>, _: UnsafeMutableRawPointer?) -> Void { 
    let list: MIDIPacketList = ptr.pointee 
    ... 
} 

您还可能发现这两个延伸部有用。

这一个(来自here派生)允许使用for pkt in listMIDIPacketList直接迭代:

extension MIDIPacketList: Sequence { 

    public func makeIterator() -> AnyIterator<MIDIPacket> { 
     var iterator: MIDIPacket? 
     var nextIndex: UInt32 = 0 

     return AnyIterator { 
      nextIndex += 1 
      if nextIndex > self.numPackets { return nil } 
      if iterator != nil { 
       iterator = withUnsafePointer(to: &iterator!) { MIDIPacketNext($0).pointee } 
      } else { 
       iterator = self.packet; 
      } 
      return iterator 
     } 
    } 
} 

而这一次增加一个MIDIPacket的方法来提取的,而不必使用的内容作为[UInt8]真正破坏的元组语法:

extension MIDIPacket { 
    public var asArray: [UInt8] { 
     let mirror = Mirror(reflecting: self.data) 
     let length = Int(self.length) 

     var result = [UInt8]() 
     result.reserveCapacity(length) 

     for (n, child) in mirror.children.enumerated() { 
      if n == length { 
       break 
      } 
      result.append(child.value as! UInt8) 
     } 
     return result 
    } 
}