Saturday, November 21, 2009

Objective-C calls Python names

I have a new (short?) project to work on that combines Python and Objective-C, and I hope it will improve my understanding of the latter.

While cruising Stack Overflow yesterday I came upon this question and answer. The issue is how to "bridge" from code in one language to another. It's easy going from Python to Objective-C, you can even do it from the command line:


>>> from Foundation import *
>>> A = NSArray.arrayWithObjects_('a','b',None)
>>> A
(
a,
b
)
>>> A.objectAtIndex_(1)
'b'
>>>


But how to go the other way, back from Objective-C into Python? Obviously, one could launch Python as a separate process, and have it write the results to disk or something (I don't know offhand how to do this from Objective-C, I'll put it on the to-do list). But we're looking for tighter integration than that.

According to bbum it's easy, you just do this:

To call from Objective-C into Python, the easiest way is to:

• declare an abstract superclass in Objective-C that contains the API you want to call
• create stub implementations of the methods in the class's @implementation
• subclass the class in Python and provide concrete implementations
• create a factory method on the abstract superclass that creates concrete subclass instances

Well, 3/4 make sense to me and the fourth sorta does! But where do you get the interpreter from?

My PyObjC Xcode projects might provide a model for this. But they get back to this problem: a lot of what I've done with Xcode, and PyObjC, is magic to me. I'd like to understand it better, but it seems hard. For example, recent projects have a file main.m which appears to start everything off, but I have no idea how it works. The older projects (2 yr) do not have a main.m. How do they work?

So, what I did, I posted a new question at Stack Overflow.

And bbum answered! Actually, Barry Wark did too (thanks). Also a yahoo helpful soul who told me about this thing called Google and PyObjC, but didn't actually read the question. Bill sounded a little exasperated, but he posted with a working solution at around 11 PM on a Friday night. That is special.

So, I have carried down the tablets from the mountaintop, and I'm going to figure it out, and I'll let you know. But just to look ahead a bit: in his solution the way you get the Python interpreter is to (wait for it) start in the interpreter. Well, of course!

And in case you try this at home, when you open the project in Xcode the "Build and Run" toolbar icon is (what's the word?) inactive. But the menu item works.