How to cast self to UnsafeMutablePointer<Void> type in swift
An object pointer (i.e. an instance of a reference type) can beconverted to a UnsafePointer<Void>
(the Swift mapping of const void *
, UnsafeRawPointer
in Swift 3) and back. In Objective-C you would write
void *voidPtr = (__bridge void*)self;// MyType *mySelf = (__bridge MyType *)voidPtr;
(See 3.2.4 Bridged casts in the Clang ARC documentation for the precise meaning of thesecasts.)
Swift has an Unmanaged
type for that purpose.It is a bit cumbersome to use because it works with COpaquePointer
instead of UnsafePointer<Void>
. Here are two helper methods(named after the Objective-C __bridge
cast):
func bridge<T : AnyObject>(obj : T) -> UnsafePointer<Void> { return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque()) // return unsafeAddressOf(obj) // ***}func bridge<T : AnyObject>(ptr : UnsafePointer<Void>) -> T { return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue() // return unsafeBitCast(ptr, T.self) // ***}
The "complicated" expression is only necessary to satisfy Swiftsstrict type system. In the compiled code this is just a castbetween pointers. (It can be written shorter as indicated in the ***
commentsif you are willing to use "unsafe" methods, but the compiledcode is identical.)
Using this helper methods you can pass self
to a C function as
let voidPtr = bridge(self)
(or UnsafeMutablePointer<Void>(bridge(self))
if the C function requiresa mutable pointer), and convert it back to an object pointer – e.g.in a callback function – as
let mySelf : MyType = bridge(voidPtr)
No transfer of ownership takes place, so you must ensure that self
exists as long as the void pointer is used.
And for the sake of completeness, the Swift equivalent of __bridge_retained
and __bridge_transfer
from Objective-C would be
func bridgeRetained<T : AnyObject>(obj : T) -> UnsafePointer<Void> { return UnsafePointer(Unmanaged.passRetained(obj).toOpaque())}func bridgeTransfer<T : AnyObject>(ptr : UnsafePointer<Void>) -> T { return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeRetainedValue()}
bridgeRetained()
casts the object pointer to a void pointer andretains the object. bridgeTransfer()
converts thevoid pointer back to an object pointer and consumes the retain.
An advantage is that the object cannot be deallocated between thecalls because a strong reference is held. The disadvantage is thatthe calls must be properly balanced, and that it can easily cause retaincycles.
Update for Swift 3 (Xcode 8):
func bridge<T : AnyObject>(obj : T) -> UnsafeRawPointer { return UnsafeRawPointer(Unmanaged.passUnretained(obj).toOpaque())}func bridge<T : AnyObject>(ptr : UnsafeRawPointer) -> T { return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()}func bridgeRetained<T : AnyObject>(obj : T) -> UnsafeRawPointer { return UnsafeRawPointer(Unmanaged.passRetained(obj).toOpaque())}func bridgeTransfer<T : AnyObject>(ptr : UnsafeRawPointer) -> T { return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()}
The relevant changes to "unsafe pointers" are described in
It seems to me that this is what withUnsafeMutablePointer
is for - to convert an arbitrary Swift pointer into a C pointer. So presumably you could do this (I have not tried it, but the code I've tested works safely):
var mself = self withUnsafeMutablePointer(&mself) { v in let v2 = UnsafeMutablePointer<Void>(v) myStruct.inputProcRefCon = v2}
func bridge<T : AnyObject>(obj : T) -> UnsafePointer<Void> {return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque())}func bridge<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()}func bridgeRetained<T : AnyObject>(obj : T) -> UnsafePointer<Void> {return UnsafePointer( Unmanaged.passRetained(obj).toOpaque())}func bridgeTransfer<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()}