2015-07-02 39 views
1

CFReadStreamSetClient在它的初始化一個C函數的回調(CFReadStreamClientCallBack),在Swift 2.0中實現c函數回調?

CFReadStreamClientCallback看起來是這樣的:

typealias CFReadStreamClientCallBack = (CFReadStream!, 
     CFStreamEventType, UnsafeMutablePointer<Void>) -> Void 

我試圖處理CFReadStreamClientCallBack C-回調函數的方法:

func callback(stream: CFReadStreamRef, 
     eventType: CFStreamEventType, 
     inClientInfo: UnsafeMutablePointer<Void>) { 
    } 

但是,當我嘗試在CFReadStreamCallback中設置回調如下,它不會編譯。

CFReadStreamSetClient(stream, registeredEvents, callback, clientContextPtr)

我知道斯威夫特與2.0有使用斯威夫特關閉與C函數回調的方式,但我似乎無法得到它的工作。有沒有人知道在這種情況下如何做到這一點?

+3

'@convention(C)'。 –

回答

4

可以作出關閉,做你喜歡這個功能做什麼:

CFReadStreamSetClient(stream, registeredEvents, { readStream, event, data -> Void in 
    // Do stuff here. 
}, clientContextPtr) 

還要注意的是C函數塊不能有一個背景,所以你不能訪問自己或任何其他從塊外部變量。 如果這不起作用,你可以在你的問題中包含編譯器錯誤?

+0

這個工作,非常感謝。我想知道你是否也知道如何處理這個問題? :''AURenderCallbackStruct( inputProc:, inputProcRefCon:&selfPtr )'' – 3254523

+1

我沒有用過AudioUnit太多,但我猜你通過使用'unsafeAddressOf(self)'得到了selfPtr,並且那個位正在工作。除此之外,你需要這樣的:'AURenderCallbackStruct(inputProc:{inRefCon,ioActionFlags,inTimeStamp,inBusNumber,inNumberFrames,ioData - > OSStatus在 \t // TODO:東西,返回OSStatus },inputProcRefCon:selfPtr)' –

+0

希望我可以給你更多的觀點:)謝謝 – 3254523

3

雨燕2.0:

給出一個函數,它接受一個函數指針和上下文:

void c_func_with_callback(void *context, void (*callback)(void *context)) 

這很容易把它從斯威夫特稱,但它不會有可能訪問的變量封閉類:

c_func_with_callback(nil) { context in 
    print("Callback in Swift!") // OK 
    self.xxx // error 
} 

如果您需要訪問該塊之外的變量,它可以使用上下文的指針存儲類:

class MyClass { 
    func hello() { 
     print("MyClass.hello()") 
    } 

    func classMethodAsCallback() { 
     let context = unsafeBitCast(self, UnsafeMutablePointer<Void>.self) 
     c_func_with_callback(context) { context in 
      let caller = unsafeBitCast(context, MyClass.self) 
      caller.hello() 
     } 
    } 
} 
let myClass = MyClass() 
myClass.classMethodAsCallback() 

使用任何封閉的回調它甚至可以:

class MyClass { 
    typealias Closure =()->() 

    func anySwiftClosureAsCallback(closure: Closure) { 
     var c = closure 
     // closure won't fit in a pointer, so take it's address first 
     let context = withUnsafePointer(&c) { 
       //(ptr: UnsafePointer<Closure>) -> UnsafeMutablePointer<Void> in 
       ptr in 
      return unsafeBitCast(ptr, UnsafeMutablePointer<Void>.self) 
     } 
     c_func_with_callback(context) { context in 
      let ptr = unsafeBitCast(context, UnsafePointer<Closure>.self) 
      let closure = ptr.memory // dereference the address 
      closure() 
     } 
    } 
} 
let myClass = MyClass() 
myClass.anySwiftClosureAsCallback { 
    print("Swift closure called") 
}