Casting between Int and closure

For C inter-op purposes I am converting closure values to 64-bit quantities and back, via obj-c:

typealias Closure = () -> Void
let v: Int64 = toInt64(closure)
...
let closure2: Closure = fromInt64(v)
closure2()

--------- objc.m ---------
typedef void (^Block)(void);

long toInt64(Block block) {
    return (long)(__bridge_retained void*)block;
}

Block fromInt64(long v) {
    return (__bridge_transfer Block)(void*)v;
}

How do I do this without Objective-c?

The Swift Unmanaged class and its toOpaque and fromOpaque methods can be used to convert object references to pointers and back. Since “everything can be converted to AnyObject” in Swift, the following should work:

typealias Closure = () -> Void

let cl1: Closure = { print("Hello") }

// Closure to pointer:
let ptr =  Unmanaged.passRetained(cl1 as AnyObject).toOpaque()

// Pointer to closure:
if let cl2 = Unmanaged<AnyObject>.fromOpaque(ptr).takeRetainedValue() as? Closure {
    cl2()
}

As in your Objective-C version, you are responsible for properly balancing the passRetained and takeRetainedValue calls.

There is also passUnretained and takeUnretainedValue which correspond to the __bridge conversion in Objective-C and do not retain or release the object.

Here ptr is an UnsafeMutableRawPointer which corresponds to void * in C. If you need an integer type then you can convert the pointer to an UInt and back with

let v = UInt(bitPattern: ptr)
let p = UnsafeRawPointer(bitPattern: v)
3 Likes