Objective-C pointer and swift

2.6k views Asked by At

I'm following an apple document, but unfortunately the examples are written on objective-c, but I have confidence with Swift language and can not understand the meaning of some things, in particular, in this example:

void RunLoopSourcesPerformRoutine (void *info){
    RunLoopSource*  obj = (RunLoopSource*)info;
    [obj sourceFired];
}

this line: RunLoopSource* obj = (RunLoopSource*)info;

the parameter: void *info indicates that info is a pointer to void, then I can put the address of any type of data structure, following various apple documents I saw that the translation of this : void *info into swift language is :

info: UnsafeMutableRawPointer?

Now, the RunLoopSource* obj = (RunLoopSource*)info; line indicates that obj is a variable of type: RunLoopSource, and to this is assigned the value of (RunLoopSource *) info, but precisely What does it mean this statement? : (RunLoopSource *) info, and how it translates in swift language ?

3

There are 3 answers

0
matt On BEST ANSWER

What you are dealing with (void *info) is a C pointer-to-void, which arrives into Swift as a form of UnsafeRawPointer. This means that type info has been cast away and that memory is being managed elsewhere.

In order to work with this thing as what you believe it to be, i.e. a RunLoopSource, you need to characterize it explicitly as a RunLoopSource. In C, you would cast, as in the example code you posted: (RunLoopSource*)info. In Swift, you rebind.

Observe that in your case this whole thing has been made just a little more complicated by the fact that this UnsafeMutableRawPointer has been wrapped in an Optional, and will have to be unwrapped before you can do anything at all.

Assuming, then, in your case, that info is really an UnsafeMutableRawPointer? bound to a RunLoopSource, you can say:

let rlsptr = info!.assumingMemoryBound(to: RunLoopSource.self)
let rls = rlsptr.pointee

Now rls is a RunLoopSource and you can work with it however you like. Keep in mind, however, that the memory is unmanaged, so you should work with it only here and now.

EDIT By the way, Apple has a really nice document on this entire matter: https://swift.org/migration-guide/se-0107-migrate.html

2
Ben Zotto On

This specific expression is a "typecast": it's saying that info, which is declared to be a pointer-to-unknown-anything (void *) is actually known by the programmer to be a pointer to a RunLoopSource. This forcibly changes the type of the expression to make the compiler happy as it is assigned to obj.

It is equivalent to using as! in Swift and is idiomatic when you know the semantics of a void * but the syntax doesn't capture it.

(This attempts to answer your question as stated but I'm not sure if you are looking for more information. If so, please clarify and me or someone more expert in unsafe pointers in Swift can help out.)

1
Jenny On

Swift really hates pointer. These 2 lines of code can be converted to Swift as

func RunLoopSourcesPerformRoutine(info: UnsafeMutableRawPointer) {
    let obj = info.assumingMemoryBound(to: RunLoopSource.self)
    obj.pointee.sourceFired()
}