Using native Objective-C methods for C Callbacks

For the modern Macintosh programmer, given the incredible power of the Objective-C programming language combined with the fact that you can inline C code directly in the Objective-C code, there are few things left wanting … almost.

One of these stickly issues is the use of C callbacks; passing the reference of a function to a function in order to later make use of it. If you’re writing up your own code from scratch this really isn’t going to come up. But if you want to use a C library in your Objective-C code, especially if you want to call an object method instead of a C function for the callback, it’s a problem very likely to come up.

Because of the Object-Oriented nature of Objective-C, it’s essentially impossible to make a callback to an object method. (Think about it; the method is part of an object instance, and because of the dynamic nature of an object, it’s impossible for the compiler to know the reference to an instance of an object) Thanks, however, to the magic of dynamic typing, even this can be done without too much problem. The one caveat is that the library (or other implementation requiring callbacks) must have the option to pass an arbitrary data reference to the same callback. Here’s how it works:

// Dummy callback object - to prevent compiler warnings
@interface CallbackObject
- (void) updateObject: (void *)data;

@implementation CallbackObject
- (void) updateObject: (void *)data { }

// The C function passed as the callback
static void updateObjectCallback(void *ptr, void *parent)
CallbackObject *parentObject = (CallbackObject *)parent;
[parentObject updateObject: ptr];

First, some background: In Objective-C, objects are generally passed around as references. For example, if we’re passing around an instance of NSObject, this will generally be in the form of an (NSObject *). In a special case, the variable self is also a reference to the current instance of itself (as opposed to the actual data). This is very useful to us for dealing with callbacks.

Consider the case of a library that manipulates an array of items. The library has a function requiring a callback that will allow you to perform some custom manipulation of each item (The callback being the function that performs the manipulation on each individual item). So, when calling the callback function, the library will pass the item reference as the first parameter, and the arbitrary reference as the second.

This is how the above example works; the callback function has two parameters: the first being a reference to a particular item, and the second being an arbitrary reference, which we decide to use as the reference to the instance of an object. We then can cast the second arbitrary reference to a type of an object containing the callback method we want to use.

But… Why the “Dummy” CallbackObject? It doesn’t even do anything? Exactly. In fact, it’s important to note that the code will work without the “Dummy” CallbackObject. We could have cast the reference to an NSObject *, or, in fact, any Objective-C object. The only reason we use CallbackObject is to prevent compiler warnings that the given object may not respond to the updateObject method. (We already know that the updateObject will exist when we call it) More on why we used this approach in a moment…

Here’s the code in a class that actually makes use of the callback function:

- (void) updateObjects:(NSObject *) object;
libUpdateObjects(library->objectList, updateObjectCallback, self);

- (void) updateObject: (void *)item
// Do stuff with the item here

Now we’ve come full circle. The class calls the updateObjects method, in turn invoking the C library function libUpdateObjects, which in turn calls updateObjectCallback on each item, passing the reference to each item, along with the reference to the current object (self).

That goes up to our previously defined callback function, which casts the reference into an object instance of type CallbackObject, and then sends a message to the method updateObjects in that instance. Note that because of the dynamic nature of Objective-C, the updateObject method in CallbackObject never gets called.

Finally, with each item, it’s back in the current instance, doing whatever is supposed to be done with the item in updateObject; and as a result, all the class variables, etc. are fully available to the method!

Granted, this could be set up slightly simpler, however, the beauty of this approach is that any class reference can be passed into the callback – there’s no limitation that requires that “self” be passed as the object reference. Suppose you had another class that also had an updateObject method – you could without reserve pass the reference to that object. (It goes for granted that the method needs to deal with the same type of ‘item’)

Finally, this may also be obvious, but if you want to have multiple callback routines, you’ll need to set up a separate callback template and method for each one. So, that’s how to use native Objective-C methods for C Callbacks.