In this tutorial we are going to take an existing ObjC application and add Python and PyObjC to it. One of the reasons why you may want to do this is because some things are much simpler in Python than in ObjC, mainly due to the rich library Python has.
At the time of this writing this tutorial only works with a framework-based
python 2.3 (also known as MacPython-2.3), it does not work with Apple's
/usr/bin/python 2.2. The reason for this is that Apple forgot to ship
the Python dynamic library, so you cannot embed this Python in your
application.
You will also need the Apple Developer Kit, and it is expected you are familiar
with using Project Builder, Interface Builder and Terminal. MacPython 2.3b2
or later is expected in the
standard location (/Library/Frameworks, with auxiliary executables
in /usr/local/bin and on your $PATH).
The application we are going to modify is Apple's SimpleComboBox example. This example shows you how to use combo boxes, but that is not what interests us right now: the application pretends to be a database application that allows you to keep notes (such as track list) for your CD collection. With such an application it feels silly that even though you want to type notes on the CD you are currently playing in iTunes you still have to retype album title, artist and genre. This is what we are going to fix: we are going to add a button "ask iTunes", which will use Python's AppleScript support to ask iTunes about the currently playing track and fill in the fields for you.
Follow these steps:
/Developer/Examples/AppKit/SimpleComboBox to work on.
Let's call this SimpleComboBoxPlus:% cp -R /Developer/Examples/AppKit/SimpleComboBox SimpleComboBoxPlus
PythonGlue.h, PythonGlue.m and PythonGlue.py from src
into the SimpleComboBoxPlus folder:% cp -R src/PythonGlue.* SimpleComboBoxPlus
PythonGlue.h and PythonGlue.m to the "Classes" group.These files contain a class PythonGlue that does nothing
visibly useful, but it has interesting side effects: when the first
class instance is initialized it will initialize the Python interpreter,
add the Resource folder of your application to the Python search path
and import any modules from that Resources folder. The first bit of
this is done by the ObjC code, the latter two by the Python code
in PythonGlue.py.
PythonGlue.py to the "Resources" group./Library/Frameworks/Python.framework.PythonGlue object be instantiated
being called early during startup. A good place to do this for the
current application is when MainMenu.nib is loaded, as it does not
contain any Python dependencies itself.Open the MainMenu.nib in Interface Builder and define a subclas of
NSObject and call the new class PythonGlue. Instantiate it. Use this
instance as the application delegate for the File Owner.
Jack: I think this method will not work if you want to use Python-based classes in your main NIB file. Suggestions for how to make sure a PythonGlue object is instantiated before our main NIB file is read are hereby requested.
Ronald: You might add
[[PythonGlue alloc] init]tomain.m, before the call toNSApplicationMain. You'd also have to create an autorelease pool before creating thePythonGlueinstance.
CDInfoDocument.nib. Select the Class View, NSObject, subclass
as ITunesCommunication. Give the class an askITunes: action.
Instantiate the class as object ITunesCommunication.askITunes: action of the ITunesCommunication
object.ITunesCommunication class.
Create a file ITunesCommunication.py in the Resources group. As this tutorial
is about using PyObjC in existing ObjC programs and not about PyObjC itself
we are going to skip the code itself and simply copy it from src/ITunesCommunication_1.py.
Note that this is not the final code yet, it is a debug version that does not
yet talk to iTunes.Double-clicking on
ITunesCommunication.pyin Project Builder may cause it to try and run the code in stead of editing it. In this case bring up the contextual menu and select "Open As..."->"Plain Text File".
iTunes.app. This leads to
the following hefty command line which you should run in the
SimpleComboBoxPlus directory:
% cd SimpleComboBoxPlus
% setenv FWPYTHON /Library/Frameworks/Python.framework/Versions/Current
% pythonw $FWPYTHON/lib/python2.3/plat-mac/gensuitemodule.py \
--output iTunes --resource --creator hook \
/Applications/iTunes.app/Contents/Resources/iTunes.rsrc
This assumes MacPython is installed in the standard place and pythonw
is on your $PATH.
iTunes package to your project: select the "Resources",
and add iTunes. Add it as a folder reference, not as a recursive group.ITunesCommunication.py to actually communicate
with iTunes. We cop out and copy it from src/ITunesCommunication_2.py.