Swift 从C风格指针访问self
我正在开发一个使用MIDI设备的应用程序。在操场上玩了几次CoreMIDI之后,我发现了如何获取MIDI输入信号,因此我实现了以下功能:Swift 从C风格指针访问self,swift,macos,cocoa,midi,coremidi,Swift,Macos,Cocoa,Midi,Coremidi,我正在开发一个使用MIDI设备的应用程序。在操场上玩了几次CoreMIDI之后,我发现了如何获取MIDI输入信号,因此我实现了以下功能: func makeInputSource() { var midiClient : MIDIClientRef = 0 var inPort : MIDIPortRef = 0 MIDIClientCreate("WobClient" as CFString, nil, nil, &midiClient) MIDIIn
func makeInputSource() {
var midiClient : MIDIClientRef = 0
var inPort : MIDIPortRef = 0
MIDIClientCreate("WobClient" as CFString, nil, nil, &midiClient)
MIDIInputPortCreate(midiClient, "WobClient_InPort" as CFString, {
(pktList: UnsafePointer<MIDIPacketList>, readProcRefCon: UnsafeMutableRawPointer?, srcConnRefCon: UnsafeMutableRawPointer?) in
let packetList : MIDIPacketList = pktList.pointee
var packet : MIDIPacket = packetList.packet
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
}
}
packet = MIDIPacketNext(&packet).pointee
}
}, nil, &inPort)
MIDIPortConnectSource(inPort, self.source, &self.source)
}
但是,当我尝试这样做时,会出现以下错误:
A C function pointer cannot be formed from a closure that captures context
所以我想知道的是,有没有一种方法可以从闭包内部访问self
,或者有没有其他方法可以在swift中使用MIDI输入
谢谢
---编辑:
如所问,修改后的代码:
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?) in
let packetList : MIDIPacketList = pktList.pointee
var packet : MIDIPacket = packetList.packet
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
}
}
let mySelf = Unmanaged<Wob>.fromOpaque(observer).takeUnretainedValue()
mySelf.slider_one?.integerValue = 25 // 25 is a test value
packet = MIDIPacketNext(&packet).pointee
}
}, &observer, &inPort)
MIDIPortConnectSource(inPort, self.source, &self.source)
}
func makeInputSource(){
变量midiClient:MIDIClientRef=0
变量输入:MIDIPortRef=0
var observer=UnsafeRawPointer(Unmanaged.passUnretained(self.toOpaque())
midclientcreate(“WobClient”作为CFString、nil、nil和midclient)
MIDInputPortCreate(midiClient,“WobClient\u InPort”作为CFString{
(pktList:UnsafePointer,readprocurefcon:UnsafeMutableRawPointer?,srcconrefcon:UnsafeMutableRawPointer?)位于
let packetList:MIDIPacketList=pktList.pointee
var packet:MIDIPacket=packetList.packet
对于uu1…packetList.numPackets{
let bytes=Mirror(反射:packet.data).children
变量参数:[UInt64]=[]
var i=数据包长度
for(1;,attr),以字节为单位。枚举(){
让字符串=字符串(格式:“%02X”,属性值为!UInt8)
参数append(UInt64(strtoul(string,nil,16)))
i-=1
if(i通常可以将一些上下文传递到C函数中,例如:
struct MyContext {
var setSliderValue: (Int) -> Void
}
var context = MyContext(setSliderValue: { sliderValue in
Dispatch.queue.async {
self.slider_one?.integerValue = sliderValue
}
))
然后将其传递给C函数:
MIDIInputPortCreate(midiClient, "WobClient_InPort" as CFString, { ... }, &context, &inPort)
let readContext = readProcRefCon!.assumingMemoryBound(to: MyContext.self)
readContext.pointee.setSliderValue(params[2])
在闭包函数中:
MIDIInputPortCreate(midiClient, "WobClient_InPort" as CFString, { ... }, &context, &inPort)
let readContext = readProcRefCon!.assumingMemoryBound(to: MyContext.self)
readContext.pointee.setSliderValue(params[2])
(未经测试编写)通常可以将一些上下文传递到C函数中,例如:
struct MyContext {
var setSliderValue: (Int) -> Void
}
var context = MyContext(setSliderValue: { sliderValue in
Dispatch.queue.async {
self.slider_one?.integerValue = sliderValue
}
))
然后将其传递给C函数:
MIDIInputPortCreate(midiClient, "WobClient_InPort" as CFString, { ... }, &context, &inPort)
let readContext = readProcRefCon!.assumingMemoryBound(to: MyContext.self)
readContext.pointee.setSliderValue(params[2])
在闭包函数中:
MIDIInputPortCreate(midiClient, "WobClient_InPort" as CFString, { ... }, &context, &inPort)
let readContext = readProcRefCon!.assumingMemoryBound(to: MyContext.self)
readContext.pointee.setSliderValue(params[2])
(未经测试而编写)似乎是一个很棒的解决方案,但是,我如何才能从上下文变量访问self
。@WesleyPeeters实际上,你可以将self
作为上下文传递,或者你可以直接将其添加到struct
。或者你可以将函数getSelf
添加到struct
。我的观点是你不需要传递self
。相反,你可以传递一个已经封装了self
的函数/闭包,就像我的setSliderValue
那样。这似乎是一个很棒的解决方案,但是,我如何能够从上下文变量访问self
e上下文,或者您可以直接将其添加到struct
。或者您可以将一个函数getSelf
添加到struct
。我的观点是,通常您不需要传递self
。相反,您可以传递一个已封装了self
的函数/闭包,就像我的setSliderValue
那样。这是ght也会有帮助:。@Martin尝试这样做:UnsafeRawPointer(Unmanaged.passUnretained(self.toOpaque())
但是,我仍然会遇到同样的错误您不能在闭包中使用self
,您必须从上下文指针重新构造它,请参见链接到答案中的让我自己=非托管…
。我从未直接引用self
,我使用了让我自己=非托管…
,之后我尝试使用e> 我自己
variable@MartinR您能将修改后的代码添加到您的问题中吗?我很确定它能起作用。这可能也会有帮助:。@MartinR尝试这样做:UnsafeRawPointer(Unmanaged.passUnretained(self.toOpaque())
但是,我仍然会遇到同样的错误您不能在闭包中使用self
,您必须从上下文指针重新构造它,请参见链接到答案中的让我自己=非托管…
。我从未直接引用self
,我使用了让我自己=非托管…
,之后我尝试使用