swift - 将 self 转换为 UnsafeMutablePointer<Void> 导致 EXC_BAD_INSTRUCTION

标签 swift macos cocoa midi coremidi

我正在开发一个 Swift 应用程序,我在其中使用来自特定的 MIDI 信号并使用它。一个例子是:我想根据输入信号移动 NSSlider 的值。所以,我所做的是创建一个 MIDI 输入流(有效),我现在需要做的是获取值并将其设置为 self.wave_mode_slider?.integerValue

我建立输入连接的方法如下:

func makeInputSource() {
    var midiClient : MIDIClientRef = 0
    var inPort : MIDIPortRef = 0
    var observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())

    MIDIClientCreate("WobClient" as CFString, nil, nil, &midiClient)
    MIDIInputPortCreate(midiClient, "WobClient_InPort" as CFString, {
        (pktList: UnsafePointer<MIDIPacketList>, readProcRefCon: UnsafeMutableRawPointer?, srcConnRefCon: UnsafeMutableRawPointer?) -> Void in
        let packetList : MIDIPacketList = pktList.pointee
        var packet : MIDIPacket = packetList.packet
        let mySelf = Unmanaged<Wob>.fromOpaque(readProcRefCon!).takeUnretainedValue()

        for _ in 1...packetList.numPackets {
            let bytes = Mirror(reflecting: packet.data).children
            var params : [UInt64] = []

            var i = packet.length
            for (_, attr) in bytes.enumerated() {
                let string = String(format: "%02X ", attr.value as! UInt8)
                params.append(UInt64(strtoul(string, nil, 16)))
                i -= 1

                if (i <= 0) {
                    break
                }
            }

            mySelf.wave_mode_slider?.integerValue = ("\(params[2])" as NSString).integerValue
            packet = MIDIPacketNext(&packet).pointee
        }

    }, nil, &inPort)

    MIDIPortConnectSource(inPort, self.source, &observer)
}

如您所见,我将观察者变量制作成这样:

var observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())

然后我将其传递给闭包并尝试这样使用:

let mySelf = Unmanaged<Wob>.fromOpaque(readProcRefCon!).takeUnretainedValue()

mySelf.wave_mode_slider?.integerValue = ("\(params[2])" as NSString).integerValue

但是,这会在声明 mySelf 的行上导致 EXC_BAD_INSTRUCTION

我也尝试使用 retained 变体,但这导致了相同的 EXC_BAD_INSTRUCTION

现在,我不是经验丰富的 swift 开发人员,尤其是涉及到这些东西时,所以我可能错过了一些明显的东西,所以有人知道为什么会这样吗?

谢谢

编辑---- 按照建议,我稍微更改了代码,

MIDIPortConnectSource(inPort, self.source, &observer)

成为

MIDIPortConnectSource(inPort, self.source, observer)

这也让我将 observer 变量更改为 UnsafeMutableRawPointer

最佳答案

在 Swift 4 上(接收抄送):

@objc func receiveMIDI(_ sender: UIButton) {

    let observer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
    MIDIClientCreate(s, nil, nil, &midiClient);
    MIDIInputPortCreate(midiClient, p, {
    (pktList: UnsafePointer<MIDIPacketList>,
        readProcRefCon: UnsafeMutableRawPointer?, srcConnRefCon: UnsafeMutableRawPointer?) in
            // callback block
            let packetList:MIDIPacketList = pktList.pointee
            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:"%02d ", attr.value as! UInt8)
                        i -= 1
                        if (i <= 0)
                        {
                            break
                        }
                }
                let midi = dumpStr.split(separator: " ", maxSplits: 2, omittingEmptySubsequences: true)
                var midiIntValues = [Int(midi[0]),Int(midi[1]),Int(midi[2].trimmingCharacters(in: .whitespaces))]
                if let src = srcConnRefCon{
                    let mySelf = Unmanaged<DetailViewController>.fromOpaque(src).takeUnretainedValue()
                    if let v = midiIntValues[2]{
                       // print("control \(midiIntValues[1]) has \(v) value")
                    }

                }
                packet = MIDIPacketNext(&packet).pointee
            }
            // end callback block
        }, nil, &inputPort);

    let sourceCount = MIDIGetNumberOfSources()
    print("source count \(sourceCount)")

    for srcIndex in 0 ..< sourceCount {
        var source = MIDIGetSource(srcIndex)
        let status = MIDIPortConnectSource(inputPort,source,observer)
        if status == noErr {
            print("Connected to inputPort")
        } else {
            print("There was an error connecting the ports!")
        }
    }
}

关于swift - 将 self 转换为 UnsafeMutablePointer<Void> 导致 EXC_BAD_INSTRUCTION,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43604662/

相关文章:

ios - 解析 DynamoDB batchGetItem JSON 输出

ios - 如何在 Release模式下启用框架的可测试性?

macos - 快速子类初始化缠结

iphone - 从类别中采用协议(protocol)

ios - 检查 NSUnderlineStyle BitMask 的值

swift - 当 TapGestureRecognizer 连接到容器 View 时,未检测到触摸按钮

swift - SDWebImage swift 崩溃

objective-c - 我可以更改 Spotlight 搜索结果中显示的名称吗?

c++ - Xcode clang 编译器中的 unsigned long long 意外行为

ios - Swift:使用抛出异常的函数进行单元测试