1

CFReadStreamSetClient has a C-function callback (CFReadStreamClientCallBack) in it's initializer,

CFReadStreamClientCallback looks like this:

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

I have a method that attempts to handle the CFReadStreamClientCallBack C-function callback:

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

but when i attempt to set the callback in CFReadStreamCallback as follows, it doesn't compile.

CFReadStreamSetClient(stream, registeredEvents, callback, clientContextPtr)

I know with Swift 2.0 there's a way to use Swift closures with C-Function callbacks but I cant seem to get it to work. Does anyone know how it can be done in this situation?

Zmey
2,6081 gold badge28 silver badges42 bronze badges
asked Jul 2, 2015 at 2:22
0

2 Answers 2

4

You can make a closure that does what you do in the function like this:

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

Also note that C function blocks can't have a context so you can't access self, or any other variable from outside the block. If that doesn't work can you include the compiler error in your question?

answered Jul 2, 2015 at 11:45
Sign up to request clarification or add additional context in comments.

2 Comments

this works, thank you so much. i was wondering if you may know how to handle this one as well? : AURenderCallbackStruct( inputProc: , inputProcRefCon: &selfPtr )
I haven't worked with AudioUnit too much but I'm guessing you got selfPtr by using unsafeAddressOf(self) and that that bit is working. Other than that you need this: AURenderCallbackStruct(inputProc: { inRefCon, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData -> OSStatus in // TODO: Stuff that returns an OSStatus }, inputProcRefCon: &selfPtr)
3

Swift 2.0:

Given a function which takes a function pointer and a context:

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

It's very easy to call it from Swift, but it won't be possible to access the variables of the enclosing class:

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

If you need to access variables outside of the block, it's possible to use the context to store a pointer to the class:

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

It's even possible to use ANY closure as a callback:

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")
}
answered Aug 8, 2015 at 3:10

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.