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.
The void pointer in C is a pointer that is not associated with any data types. It points to some data location in the storage. This means that it points to the address of variables. It is also called the general purpose pointer. In C, malloc() and calloc() functions return void * or generic pointers.
A void pointer is a pointer that can point to any type of object, but does not know what type of object it points to. A void pointer must be explicitly cast into another type of pointer to perform indirection. A null pointer is a pointer that does not point to an address. A void pointer can be a null pointer.
It's Shorthand writing. In Objective-C, any character , numeric or boolean literal prefixed with the '@' character will evaluate to a pointer to an NSNumber object (In this case), initialized with that value. C's type suffixes may be used to control the size of numeric literals.
The (void) indicates the return type. This method doesn't return anything, so its result can't be assigned to anything.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With