How do you pass a C callback in Swift? Consider this example:
class AudioQueue {
var desc : AudioStreamBasicDescription
var queue : AudioQueue?
func audioQueueHandleBuffer(ctx : UnsafeMutablePointer<()>,
inAQ : AudioQueue!,
inBuffer : AudioQueueBufferRef) {
// do stuff
}
func initialize() {
// this does not work!
var err = AudioQueueNewOutput(&desc, audioQueueHandleBuffer,
nil, nil, nil, 0, queue)
// ...
}
}
Swift closures and functions are decidedly not C functions. They exist in a weird halfway state between C++ members and Objective-C blocks, so you'll have to move any callbacks into an Objective-C file and take a block or have some other means of calling back to Swift. For example you might have your own version of the relevant AVFoundation functions take a block:
void audioQueueHandleBuffer(void *ctx, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
NSCAssert(ctx != NULL, @"Cannot execute NULL context block.");
void(^block)(AudioQueueRef, AudioQueueBufferRef) = (__bridge void(^)(AudioQueueRef, AudioQueueBufferRef))ctx;
return block(inAQ, inBuffer);
}
OSStatus CFIAudioQueueNewOutput(AudioStreamBasicDescription *desc, void(^callback)(AudioQueueRef, AudioQueueBufferRef), AudioQueueRef *queue) {
return AudioQueueNewOutput(desc, audioQueueHandleBuffer, (__bridge_retained void *)([callback copy]), nil, nil, 0, queue);
}
Then just pass your function through like you would expect in Swift.
class AudioQueue {
var desc : AudioStreamBasicDescription
var queue : AudioQueueRef
func audioQueueHandleBuffer(inAQ : AudioQueueRef, inBuffer : AudioQueueBufferRef) {
// do stuff
}
func initialize() {
var err = CFIAudioQueueNewOutput(&desc, audioQueueHandleBuffer, &queue)
// ...
}
}
It's an incredibly painful workaround for a problem that you shouldn't be trying to express in Swift. Code that must manipulate pointers, especially function pointers, is best left in a C or Objective-C file. Otherwise, you're just fighting an unnecessary battle against the language -especially because it has such great support for C and Objective-C interoperability.
With Swift 2.0 it is now possible to set up the callback in pure Swift! Please check http://oleb.net/blog/2015/06/c-callbacks-in-swift/ and Swift 2 Cannot invoke 'FSEventStreamCreate' with an argument list of type for inspiration :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With