Saturday, November 21, 2009

Objective-C calls Python names (2)

I'm working through an example (from Bill Bumgarner) of calling Python from Objective-C---at least I think that's what we're doing. Who is calling whom is a bit circular, as you will see.

The first class to consider is an Objective-C class, and it's an abstract class. That is, it is not designed to be instantiated as is but should instead be extended or subclassed, and the subclass instantiated. The subclassing stuff will happen in Python.

The class definition appears a little complicated, but it turns out that the complications are not essential to the problem. The big picture is that we declare an instance variable and methods, and these methods will later get new definitions in Python. Just in case we forget, the methods in this (abstract) class call what looks like a very strange function:


void SubclassResponsibility(id classOrInstance, SEL _cmd) {
NSString *reason = [NSString
stringWithFormat: @"Must subclass %s and override the method %s.",
object_getClassName(classOrInstance), sel_getName(_cmd)];
@throw [NSException exceptionWithName: @"SubclassResponsibility"
reason: reason
userInfo: nil];
}


This guy is not part of the @implementation, but is at the head of the file. Not sure what that means. I guess it's just a function whose definition is available to us now. Why is it done this way?

SubclassResponsibility is called in each of the "stub" methods, like this:

SubclassResponsibility(self, _cmd);

Hmm... Then I remember, there are not one but two special silent arguments that are available, that the Objective-C runtime sends to a function: self, and the name or more accurately, the selector, which is called _cmd. So we pass this on to SubclassResponsibility in order to let the errant programmer know which function he failed to implement in the subclass. And then throw an exception. And Bill tells us that---way back when---the forerunner of NSObject used to declare this method.

So that's it. An abstract Objective-C class called AbstractClass with methods that will be redefined later, and it will also be compiled into a "bundle."

Oh yes, there is a a class method:

+ namedInstance: (NSString *) a Name

which here at least doesn't seem to return anything...but will return an instance from Python.