views:

665

answers:

3

bbum posted an outline of how to do this, but I'm unable to complete the details. Where does the Python code go, and how will my Objective-C code know about it? How would I do it compiling on the command line?

+2  A: 

Google is your friend. Performing a search on the string "Cocoa Python" quickly turned up PyObjc.

Lyndsey Ferguson
Isn't that discontinued in Snow Leopard?
Georg
I don't think so, I just gave a demo on PyObjC last week on Snow Leopard.
Lyndsey Ferguson
PyObjC is included with Snow Leopard and is very much still supported by Apple.
Barry Wark
The PyObjC templates are no longer included with Xcode since the release cycles of Xcode are much longer than of PyObjC. You can still download the templates from the PyObjC project website (http://pyobjc.sourceforge.net/)
Barry Wark
I have used PyObjC---it "wraps" Objective-C for Python. I want to know how to go the other way. Tom
telliott99
Oh, it wasn't clear that you wanted to do this. You may want to revise the question.
Lyndsey Ferguson
+2  A: 

Unfortunately the story for using Python via PyObjC from within an Objective-C app is not very good at the moment. py2app which ships with PyObjC can compile loadable bundles (i.e. can be loaded via NSBundle), which seems like the best approach: define an NSObject subclass in python that implements a protocol (obtained via objc.protocolNamed) that you define in Objective-C, then compile this python file into a loadable bundle via py2app (which uses a standard setup.py). Unfortunately, py2app hasn't had much love, especially the plugin (loadable bundle) target, and a serious memory leak was introduced sometime around 10.5 such that any data passed from python to Objective-C from a py2app-compiled bundle leaks. Yuck.

PyObjC manipulates the Objective-C runtime in accordance with the ObjC-related code executed in Python, thus to be able to call python code from Objective-C, the general outline goes like

  1. Write PyObjC wrapper around python code
  2. Execute code declaring PyObjC wrapper to add these definitions to the ObjC runtime
  3. Call PyObjC wrapper from Objective-C. Because it's declared at runtime, the symbols aren't available at compile time, so you'll have to use NSClassFromString et al. to instantiate the class. It's helpful to declare a @protocol with the appropriate methods so that the Objective-C compiler doesn't complain about missing methods.

If you have flexibility, the best option is to use the Cocoa-Python app templates (i.e. create a Python app), and then load your Objective-C code as a loadable bundle from within Python. This takes care of managing the Python interpreter for you.

Otherwise, with the code in main.m of the Cocoa-Python app template, you should be able to create a Python interpreter, execute your PyObjC code and then continue on. Obviously, the interpreter needs to be kept running so that your python code can execute, so you'll likely have to do this from a separate thread. As you can see this can get a little hairy. Better to go with the Python app, as described above.

Keep in mind that PyObjC is not guaranteed to play well with the Objective-C garbage collector, so all of these options require that your Objective-C code not use GC.

Barry Wark
+9  A: 

Source here:

Calling Python From Objective-C

I have posted a full explanation of how to do this to my weblog as it is quite a bit longer than something I would post here.

The abstract summary remains the same: use an abstract class to provide the type information necessary to make the C compiler happy and the metadata necessary to make the bridge happy.

bbum
Very nice write up. I think the sticky point is still how to set things up to call into python without the original python call into Objective-C. In other words, how can I call into python code from within my existing Objective-C app? or How can I write plugins for my Objective-C app using python?
Barry Wark