草庐IT

xcode - Swift 2 到 swift 3 转换 Midi 输入

coder 2023-09-14 原文

我希望有人可以帮助我使用 Xcode 8 和 swift 3 我有一个 Playground 文件 Xcode 7 swift 2,它涉及 Midi 输入的 Midi 回调,在 7 中一切正常

我尝试转换为 8,它引发了关于内存的错误和一些我认为不严重的名称更改,我还使用 PlaygroundSupport 重新定义了无限循环 但是我无法克服的错误涉及 MyMIDIReadProc at

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

错误说 无法将类型“(pktList: UnsafePointer, readProcRefCon: UnsafeMutablePointer, srcConnRefCon: UnsafeMutablePointer) -> Void”的值转换为预期的参数类型“MIDIReadProc”(又名“@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

最佳答案

指针类型在 Swift 3 中发生了巨大变化。许多基于 C 的 API 的签名也相应地发生了变化。

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

尝试更改函数头:

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

闭包声明:

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

Swift 以这种方式完美地推断参数类型。

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

    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。)


在 Swift 3 中,指针不能为 nil,可空指针用 Optionals 表示。您可能需要许多其他修复才能在 Swift 3 中使用基于 C 的 API。

关于xcode - Swift 2 到 swift 3 转换 Midi 输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38258368/

有关xcode - Swift 2 到 swift 3 转换 Midi 输入的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  4. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  5. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  6. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  7. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

  8. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  9. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  10. ruby-on-rails - 将字符串转换为 ruby​​-on-rails 中的函数 - 2

    我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。

随机推荐