An Objective-C/Perl Bridge

Reading Objective-C Documentation

One major obstacle that stands in the path of a Cocoa-Perl developer is the fact that most of the documentation and example code that you'll find is written with Objective-C in mind. Not to fear, however - Objective-C is not all that hard to read, and by learning a few simple rules, you'll be translating Objective-C example code into Perl in no time.

Objective-C Messages

Messages and methods are closely related in Objective-C. So closely, in fact, that many people confuse the two. In practical terms, they are similar, and the most common result of sending a message is that a method of the same name is called to handle it.

At a very low level, Objective-C methods are similar to Perl methods. They are simply functions that take as their first argument a pointer to the object to which the message was sent, and as the second a special sort of string known as a selector, which identifies the message that was sent. These two arguments are hidden away by some "syntax sugar," both when the message is sent and in the method that handles it, but they're there nonetheless.

A message is a much more dynamic construct than a method. The method that will be called in order to handle a given message is determined at run-time. That is why the message name is sent as the second parameter to the method - it's possible, although uncommon, for a method to be called in response to any number of messages. In such a situation, the method could use its second parameter to determine which method to call in response to the message it received. (If you're curious, CamelBones does exactly that - a single Objective-C method is registered to handle all messages destined for Perl methods. It uses the message name to decide what Perl method should be called to handle it.)

The Syntax of a Message

Because Perl is heavily influenced by C, many C constructs are virtually identical to those used by Perl. Because Objective-C is, for the most part, identical to C, you'll find these common syntax features fairly easy to read. For/while loops and if/else statements, for example - some of the most commonly-used constructs in all three languages - share virtually identical syntax in C, Objective-C, and Perl.

One unique addition that Objective-C makes to "vanilla" C, however, is the message sending syntax, which encloses the target and the message to send to it in square brackets. Assuming that a simple message named "message", which takes no arguments, is to be sent to an object "target", the message would be written like this:

[target message];

In Perl, messages are sent to Cocoa objects using Perl's traditional method syntax. So, the above example would be coded in Perl like this:

$target->message();

Arguments to Messages

Messages, like functions, can take arguments. Unlike function arguments, however, arguments sent with messages have names. Cocoa is well-designed in this regard, as well - most of them have names that are quite descriptive and consistent. Take, for example, the message you would send to an NSMutableDictionary object to add an object to it. The message takes two arguments - the object to add, and the key to associate with it. In Objective-C, it would be written like this:

[theDictionary setObject:theObject forKey:theKey];

Each parameter in the above line of code is preceded by a colon - those colons, and the names of the parameters, are part of the message name. The message being sent by this example is "setObject:forKey:". To send such a message from Perl, simply replace the colons with underscores, remove the trailing underscore (if any), and use Perl's traditional method syntax:

$theDictionary->setObject_forKey($theObject, $theKey);

When writing methods that respond to messages sent to Perl, the same translation rules are followed. For example, to respond to an action message named "okButtonClicked:", you'd define the following method:

sub okButtonClicked {
        my ($self, $sender) = @_;
}

"$sender" in the above example is a standard argument that is sent by all GUI widgets when they send their action messages. It is simply a reference to the widget that is sending the message.

Selectors

Above, I mentioned that selectors are specially encoded strings. Because Objective-C is such a dynamic environment, these strings can be created and used at runtime. In support of such endeavors, a selector can be sent as an argument with a message, or returned from one. For example, normally you would use Interface Builder to define what action messages are sent by a GUI widget. It is also possible to do so, however, by sending the widget a setAction: message, which takes a selector as its sole argument.

In Objective-C, variables that will hold selectors are declared as type SEL, and the @selector() directive used to encode the selector itself. For example, in order to tell the GUI widget "myWidget" to send the action message "doSomething:" when it's activated, you would do the following:

SEL mySelector = @selector(doSomething:);
[myWidget setAction:mySelector];

The @selector() directive is also often used "inline," without storing the selector in a variable:

[myWidget setAction:@selector(doSomething:)];

Another way you may see selectors created is with the NSSelectorFromString() function, which takes an NSString object as its one argument:

SEL mySelector = NSSelectorFromString(someString);
[myWidget setAction:mySelector];

You can treat selectors in Perl as ordinary strings, i.e. scalars:

$myWidget->setAction("doSomething:");