14

I have a function:

  myFunction (MyProc callback, void * ref)

This function is called from within an Objective-C class. The function is passed a pointer to the callback (a function in the class) and a reference. The reference is necessary because the callback is called statically and therefore doesn't have a context. The ref can be used to provide a context to the callback.

I want to be able to pass the Objective-C class as the reference. So the question is:

How do I cast an NSObject to a void * and how do I cast a void * as an NSObject.

Thanks in advance.

3 Answers 3

38

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

Sign up to request clarification or add additional context in comments.

Comments

10

I assume you are using ARC. You can use something like this when calling myFunction

id ref = ...; // your Objective-C object
myFunction(callback, (__bridge_retained void *) ref);

In your callback, you must transfer the ownership back:

void callback(void* refPtr) {
    id refObj = (__bridge_transfer id) refPtr;
}

Replace id with your object type as appropriated.

3 Comments

When I try to cast to an id it says: Incompatible types casting void * to id with a bridge transfer cast
I put my callback function in my test project exactly the same as I post here and I don't see such compile error. Can you try that?
If the callback will be called more than once, __bridge_transfer should not be used as it will transfer ownership to ARC and the object will be automatically released.
1

Answer: in no way. void * is implicitly compatible with any pointer type, so if you have an object, which is a pointer of type id (alias for struct objc_object *), you can simply pass it where the void pointer is needed, without casting. Example:

// this is the declaration of the callback function:
void callback(void *context);

// then you can call it like this:
SomeClass *obj = [[SomeClass alloc] init];
callback(obj);

14 Comments

When I try to pass 'self' to the function I get a compiler warning: saying that an implicit conversion of Objective-C pointer to C pointer type void * requires bridging cast.
@BenSmiley when you do that (what?), then what?
When I do a bridging cast I get a BAD_ACCESS exception casting the void * back to an Objective-C object.
@BenSmiley uhm. Try turning off ARC for a moment, then retry. What does that do?
Without ARC it works. But I'm planning to use ARC for this project.
|

Your Answer

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.