Pass an Objective-C object to a function as a void * pointer

Do something like this:

void func(void *q)
{
    NSObject* o = CFBridgingRelease(q);
    NSLog(@"%@", o);
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSObject* o = [NSObject new];
        func((void*)CFBridgingRetain(o));
    }
    return 0;
}

Note that CFBridgingRetain() and CFBridgingRelease() are macros around compiler attributes. Feel free to use either. I like the API variant as it is in more common use in our codebases and it is more explicitly / less confusing.

CFBridgingRetain() effectively hard-retains the object that must be balanced by a CFBridgingRelease(). It also happens to return a CFTypeRef which is compatible with a cast to void*. CFBridgingRelease() effectively undoes that hard-retain and, thus, q will only remain valid within the scope that o is valid.

Valid for basic callbacks, but you’d probably not what that with a void *context; type thing that has to stick around for a while. For that:

void callback(void *context)
{
    // grab an ARC aware reference without impacting hard-retain
    NSObject* o = (__bridge NSObject *)(context);
    NSLog(@"%@", o);
}

void freeContext(void *context)
{
    // release the hard-retain
    CFBridgingRelease(context);
}

Note that Xcode is quite good about suggesting exactly what you should do if you leave out the cast / API call. It even explains the meanings of each of the alternative solutions (I relied on this heavily until I could keep ’em straight in my head).

Leave a Comment