pyobjc / Doc / intro.html

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>
An introduction to PyObjC</title>
<title>
Contents</title>
</head>
<body>
<h2>An introduction to PyObjC</h2>
<!-- :authors: Ronald Oussoren
:contact: pyobjc-dev@lists.sourceforge.net
:URL: http://pyobjc.sourceforge.net/
:copyright: 2003 The PyObjC Project -->
<h2>Contents</h2>
<ul>
<li><a href="#preface" id="id4" name="id4">Preface</a></li>
<li><a href="#objective-c-for-pyobjc-users" id="id5" name="id5">Objective-C for PyObjC users</a></li>
<li><a href="#overview-of-the-bridge" id="id6" name="id6">Overview of the bridge</a><ul>
<li><a href="#classes" id="id7" name="id7">Classes</a></li>
<li><a href="#methods-and-functions" id="id8" name="id8">Methods and functions</a></li>
<li><a href="#reference-counting" id="id9" name="id9">Reference counting</a></li>
<li><a href="#informal-protocols" id="id10" name="id10">(Informal) protocols</a></li>
<li><a href="#cocoa-bindings" id="id11" name="id11">Cocoa Bindings</a></li>
</ul>
</li>
<li><a href="#cocoa-for-python-programmers" id="id12" name="id12">Cocoa for Python programmers</a></li>
<li><a href="#notes-on-specific-tasks" id="id13" name="id13">Notes on specific tasks</a><ul>
<li><a href="#working-with-threads" id="id14" name="id14">Working with threads</a></li>
<li><a href="#finalizers" id="id15" name="id15">Finalizers</a></li>
</ul>
</li>
<li><a href="#building-applications" id="id16" name="id16">Building applications</a><ul>
<li><a href="#pure-python-buildapp-py" id="id17" name="id17">&quot;Pure Python&quot; :  buildapp.py</a></li>
<li><a href="#ide-approach-xcode" id="id18" name="id18">&quot;IDE approach&quot; : Xcode</a></li>
</ul>
</li>
</ul>
<h2><a href="#id4" name="preface">Preface</a></h2>
<p>PyObjC is a bridge between Python and Objective-C. It allows you to write 
Python scripts that use and extend existing Objective-C class libraries, 
most importantly the <a href="http://developer.apple.com/techpubs/macosx/Cocoa/CocoaTopics.html">Cocoa libraries</a> by <a href="http://www.apple.com/">Apple</a>.</p>
<p>This document describes how to use Objective-C class libraries from Python
scripts and how to interpret the documentation of those libraries, from the 
point of view of a Python programmer.</p>
<h2><a href="#id5" name="objective-c-for-pyobjc-users">Objective-C for PyObjC users</a></h2>
<p>It is necessary to understand a little bit of Objective-C to use PyObjC,
this helps you to better understand the class libraries and makes it easier
to read (and translate) example code.</p>
<p>Objective-C is an object-oriented programming language that is an extension 
of C and borrows heavily from Smalltalk. It features single inheritance with
(in theory) multiple root classes and dynamic dispatch of methods. This is
basically the same as Python with single inheritance.</p>
<p>An important difference between Python and Objective-C is that the latter is
not a pure object-oriented language. Some values are not objects, but values
of plain C types, such as <code><span>int</span></code> and <code><span>double</span></code>. These basic C types can also
be used as the types of arguments and the return value of methods.</p>
<p>Object allocation and initialization are explicit and separate actions in 
Objective-C. The former is done by the class-method <code><span>alloc</span></code>, while the
latter is done by instance-methods whose name customarily starts with <code><span>init</span></code>.</p>
<p>Objective-C code looks just like plain C code, with some easily recognizable
extensions for the Object-Oriented parts of the language. An example class
declaration (usually found in <code><span>.h</span></code> files) and implementation (usually found
in <code><span>.m</span></code> files) are listed below. Class declarations are easily recognized as 
blocks of code between <code><span>@interface</span></code> and <code><span>@end</span></code>, and similarly the 
implementation is between <code><span>@implementation</span></code> and <code><span>@end</span></code>. Calling methods
is done using expressions enclosed with brackets (name?), e.g. 
<code><span>[foo</span> <span>method]</span></code>.  This is the same as <code><span>foo.method()</span></code> in Python.</p>
<p>A class declaration:</p>
<pre>
@interface MYClass : MySuperClass
{
   id  anInstanceVariable;
   int anotherInstanceVariable;
}

+aClassMethod;

-(int)anInstanceMethodWithArg1:arg1 andArg2:(BOOL)arg2;
@end
</pre>
<p>A class implementation:</p>
<pre>
@implementation MYClass

+aClassMethod
{
     id res = [[MYClass alloc] init];
     return res;
}

-(int)anInstanceMethodWithArg1:arg1 andArg2:(BOOL)arg2
{
     int res;

     if (arg2) {
             res = [self fooWith:arg1];
     } else {
             res = [arg1 bar];
     }
}

@end
</pre>
<p>Objective-C also features exceptions, but as they are mostly used for disaster
recovery and not for normal error handling you won't see them very often
in example code. Read <a href="http://developer.apple.com/techpubs/macosx/Cocoa/ObjectiveC/index.html">The Objective-C Programming Language</a> if you want to
know more about exceptions in Objective-C.</p>
<p>One thing to keep in mind when translating Objective-C snippets to python is
that it is valid to call methods on <code><span>nil</span></code> (that is the NULL pointer). Those
method calls are ignored by the runtime. The value <code><span>nil</span></code> is represented in
Python by the <code><span>None</span></code>; this means to access a non-existing method will raise
<code><span>AttributeError</span></code>.</p>
<p>For more information about Objective-C see:</p>
<ul>
<li><a href="http://developer.apple.com/techpubs/macosx/Cocoa/ObjectiveC/index.html">The Objective-C Programming Language</a> at <a href="http://www.apple.com/">Apple</a>.</li>
</ul>
<h2><a href="#id6" name="overview-of-the-bridge">Overview of the bridge</a></h2>
<h3><a href="#id7" name="classes">Classes</a></h3>
<p>Objective-C classes are visible as (new-style) Python classes and can be 
subclassed just like normal Python classes. All the usual introspection
mechanisms work as well, as do __slots__ and descriptors. The major 
differences between normal Python classes and Objective-C classes are the way 
you create instances and the fact that Objective-C methods have odd names.</p>
<p>You can use multiple inheritance with Objective-C classes, as long as the
Objective-C class is the first base-class and there is only one Objective-C 
base-class. E.g. it is not possible to subclass from multiple Objective-C classes
at the same time. Multiple inheritance should also not be used to mix-in
different implementations for Objective-C methods. It will not work and
you won't get errors about this.</p>
<p>Another thing to keep in mind is that the names of Objective-C classes must
be unique, including across Python modules. That is, it is <i>not</i> possible
to have two Python modules that define a class with the same name. If you write 
classes that will be used outside of a single project it is customary to pick a 
(short) prefix and stick that in front of all class names, e.g. Apple <code><span>NS</span></code> 
as the prefix in the <a href="http://developer.apple.com/techpubs/macosx/Cocoa/CocoaTopics.html">Cocoa libraries</a>.</p>
<p>As described in <a href="#objective-c-for-pyobjc-users">Objective-C for PyObjC users</a> the creation of Objective-C 
objects is a two-stage process. You first call the class method <code><span>alloc</span></code>, and
then call some variation of <code><span>init</span></code> to initialize the objects. The newly
created object is the result of the call to <code><span>init</span></code>. Most classes have 
convenience class methods that combine the calls to <code><span>alloc</span></code> and <code><span>init</span></code>.</p>
<h3><a href="#id8" name="methods-and-functions">Methods and functions</a></h3>
<p>Objective-C methods are bridged to Python callables. Because Objective-C method 
names can contain colons it is necessary to translate methods names. The rules
for translation are:</p>
<ul>
<li>Concatenate all elements of the method name: <code><span>someMethod:withFoo:andBar:</span></code></li>
<li>Then convert all colons to underscores: <code><span>someMethod_withFoo_andBar_</span></code></li>
</ul>
<p>It is possible to use Python keywords as method names in Objective-C. To access
or define such methods append two underscores to its name (e.g. <code><span>class__</span></code>). 
This is currently only supported for <code><span>raise</span></code> and <code><span>class</span></code> because those are
the only Python keywords that are actually used in Cocoa.</p>
<p>Wrapped/bridged methods (and functions) have the same number of arguments
as the corresponding Objective-C method or function, unless otherwise noted
in the documentation (<a href="api-notes-macosx.html">Notes on supported APIs and classes on MacOS X</a> for
Cocoa on MacOS X).</p>
<p>One group of exceptions to this rule can be described in a global way. Some
methods and functions have pointers as arguments, specifically pointers to
a single value that is passed in and/or out of the function. These arguments
are sometimes called <i>pass by reference</i> arguments, and can be subdivided into
three types of arguments: <code><span>in</span></code> arguments are used to pass data to the 
function, <code><span>out</span></code> arguments are used to pass data from the function (e.g. and
additional return value) and <code><span>inout</span></code> arguments are a combination of the two.</p>
<p>The <code><span>in</span></code> and <code><span>inout</span></code> arguments for a method are also present in the Python
interface for that method (or function). In python the value passed to the
function is a &quot;normal&quot; argument. <code><span>Out</span></code> arguments are not present in the 
argument list of the Python function.</p>
<p>If a function (or method) has one or more output arguments (<code><span>out</span></code> or 
<code><span>inout</span></code>) the output values are returned as part of the return value of the
method. That is, the return value of the function is a tuple containing
the return value of the C function (or method), followed by the values of
the <code><span>out</span></code> in <code><span>inout</span></code> arguments in the order the are present in the argument
list. If the C function (or method) has return type <code><span>void</span></code>, the tuple contains
only the output arguments. As a final complication, methods with a single output
argument and return type <code><span>void</span></code>, have the value of the output argument as
the return value (e.g. not a tuple containing the return value).</p>
<p>The rules for pass by reference arguments may look quite complicated, but
it turns out this is very straightforward when working with them.</p>
<p>As an example of a method with two output arguments, NSMatrix has a method
named <code><span>getNumberOfRows_columns_</span></code> with the following signature:</p>
<pre>
(void)getNumberOfRows:(int *)rowCount columns:(int *)columnCount
</pre>
<p>You use this method in python like this:</p>
<pre>
rowCount, columnCount = matrix.getNumberOfRows_columns_()
</pre>
<p>When a function or method has an array of values and the length of that array
as arguments, you can pass <code><span>None</span></code> as the length. The length of the sequence
that is used for the array of values is passed to Objective-C as the length
argument.</p>
<p>XXX: Add information about <code><span>array.array</span></code> rules.</p>
<p>XXX: We don't use the right functions for conversion to C-arrays throughout
the bridge (yet), the information is therefore not entirely correct.</p>
<p>When you define methods in a subclass of an Objective-C class, the bridge has
to tell the Objective-C runtime what the signature of those methods is. The
basic rule is that all arguments as well as the return value are objects (just
like with normal Python methods). The bridge will automatically pick a better 
signature when it has more information available. Specifically, if you 
override an existing method the bridge will assume you want to use the same
method signature. And furthermore, if you implement a method in an (informal)
protocol known to the bridge it will use the signature from the corresponding
method in that signature.</p>
<p>The end result is that you almost never have to add information about the
signature of methods. The only known case where you have to tell the bridge
about the signature of a method is the call-back method for sheets. You can
use the function <code><span>PyObjCTools.AppHelper.endSheetMethod</span></code> to create an object
that contains the right information. This function is used like 
<code><span>staticmethod</span></code> and <code><span>classmethod</span></code> (as introduced in Python 2.2).</p>
<p>For complete control of the mapping to Objective-C you can use the function
<code><span>objc.selector</span></code>. See the documentation of the <code><span>objc</span></code> module for the
arguments you can use with this function. It is normally used like this:</p>
<pre>
class MyObject (NSObject):
        def someMethod_(self, arg):
                pass

        someMethod_ = objc.selector(someMethod_, ...)
</pre>
<h3><a href="#id9" name="reference-counting">Reference counting</a></h3>
<p>The <a href="http://developer.apple.com/techpubs/macosx/Cocoa/CocoaTopics.html">Cocoa libraries</a>, and most (if not all) other class libraries for 
Objective-C use explicit reference counting to manage memory. The methods
<code><span>retain</span></code>, <code><span>release</span></code> and <code><span>autorelease</span></code> are used to manage these 
reference counts. You won't have to manage reference counts in Python, the
bridge does all that work for you (but see <a href="api-notes-macosx.html">Notes on supported APIs and classes 
on MacOS X</a> for some advanced issues).</p>
<p>The only reasons reference counts are mentioned at all are to tell you about
ignoring them, and more importantly to introduce you to some issues w.r.t. 
reference counting.</p>
<p>It turns out that Cocoa uses a primitive form of <a href="http://www.python.org/doc/current/lib/module-weakref.html">weak references</a>. Those 
are not true <a href="http://www.python.org/doc/current/lib/module-weakref.html">weak references</a> as in Python, but use-cases where an object 
stores a reference to another object without increasing the reference count
for that other object. The bridge cannot solve the issues this introduces
for you, which means that you get hard crashes when you're not careful when
dealing with those <a href="http://www.python.org/doc/current/lib/module-weakref.html">weak references</a>.</p>
<p>The basic rule to deal with weak references is: make sure objects stays
alive as long as someone might have a weak reference to them. Due to the way
the bridge works, this means that you must make sure that you don't create
weak references from Objective-C to a plain Python object. The Python
object stays alive, but the proxy object as seen by the Objective-C code is
actually an autoreleased object that will be cleaned up unless the Objective-C
code increases its reference count.</p>
<p>The document <a href="api-notes-macosx.html">Notes on supported APIs and classes on MacOS X</a> contains 
information about classes that work with weak references. The most important
are notification centers and <code><span>NSOutlineView</span></code>, to be exact: the outline view
stores weak references to the objects return by the method 
<code><span>outlineView:child:ofItem:</span></code> of its data source. The easiest way to avoid
crashes with outline views is to make sure that you model for the view uses
subclasses of <code><span>NSObject</span></code> to represent the nodes in the outline view.</p>
<p>Another gotcha is when you're manually allocating and assigning delegate(-like)
objects: most of the time <code><span>obj.setDelegate_()</span></code> will <i>not</i> retain the 
delegate, so you must keep a reference manually.</p>
<h3><a href="#id10" name="informal-protocols">(Informal) protocols</a></h3>
<p>Cocoa defines a number of formal and informal protocols that specify methods
that should be implemented by a class if it is to be used in a specific role,
such as the data source for an NSTableView.</p>
<p>Those protocols are represented by instances of <code><span>objc.informal_protocol</span></code>. The
only ones that have to care about these objects are the maintainers of 
wrappers around Objective-C frameworks: they have to keep these protocol
wrappers up-to-date.</p>
<p>PyObjC will automatically use the information in the <code><span>informal_protocol</span></code> 
objects to add the right method signatures to methods, and to warn about
classes that partially implement a protocol.</p>
<h3><a href="#id11" name="cocoa-bindings">Cocoa Bindings</a></h3>
<p>In Mac OS X 10.3 Apple introduced <i>Cocoa Bindings</i>, a method to make it easier
to create and use <i>Controller</i> objects.</p>
<p>Use <code><span>objc.accessor</span></code> to create accessor methods that conform to the 
expectations of Cocoa Bindings.</p>
<h2><a href="#id12" name="cocoa-for-python-programmers">Cocoa for Python programmers</a></h2>
<p>Cocoa frameworks are mapped onto Python packages with the same name; that is
the classes, constants and functions from the AppKit framework are available
after you import <code><span>AppKit</span></code> in your Python script.</p>
<p>These helper modules contain <i>only</i> functions, constants and classes that 
wrap items in the corresponding framework. All utility functions and classes 
are located in the <code><span>PyObjCTools</span></code> package and <code><span>objc</span></code> module. Note that it
is possible to use <code><span>pydoc</span></code> (or the <code><span>help()</span></code>) function with the framework
wrappers, but that this is not very useful for the entire module due to the
size of these modules.</p>
<p>This makes it easier to find documentation for an item: if you import it 
from the wrapper module for an Objective-C framework the documentation for
that item can be found in the documentation for the framework; otherwise the
item is documented in the PyObjC documentation.</p>
<p>The module <code><span>PyObjCTools.NibClassBuilder</span></code> can be used to make working with 
NIB files more convenient. This module can be used to extract information 
about classes from NIB files, both as a standalone tool generating source code 
and during runtime. See the online documentation for this module for more
information.</p>
<p>PyObjC includes a number of examples that show how to use Cocoa from
Python. The <a href="../Examples/00ReadMe.html">PyObjC Example index</a> contains an overview of those examples.</p>
<p>More information on Cocoa programming can be found at:</p>
<ul>
<li><a href="http://developer.apple.com/techpubs/macosx/Cocoa/CocoaTopics.html">Cocoa documentation at the Apple developer website</a></li>
<li><a href="http://developer.apple.com/samplecode/Sample_Code/Cocoa.htm">Cocoa examples at the Apple developer website</a></li>
<li><a href="http://www.stepwise.com/">stepwise.com</a></li>
<li>Your local bookstore or library</li>
</ul>
<h2><a href="#id13" name="notes-on-specific-tasks">Notes on specific tasks</a></h2>
<h3><a href="#id14" name="working-with-threads">Working with threads</a></h3>
<p>When you create a thread and want to use PyObjC from that thread you will
have to create an <code><span>NSAutoreleasePool</span></code> in that thread and clean it up when
you're done. The easiest way to that is to create an instance of that class
bound to a local variable. If the thread is long-lived you may want to arrange
for recycling the pool once in a while.</p>
<p>There are some limitation w.r.t. threading. You cannot use <code><span>NSThread</span></code> to 
create new threads, but must use the python primitives instead.</p>
<p>You must also make sure that Objective-C only makes calls to Python from a 
thread that owns the Python GIL (that's also the reason for not being able 
to use <code><span>NSThread</span></code> to create new threads).  This restriction will be lifted
in a future version of PyObjC (at least when using Python 2.3).</p>
<h3><a href="#id15" name="finalizers">Finalizers</a></h3>
<p>In Python you can use the method <code><span>__del__</span></code> to clean up resources when your
object is garbage collected. In Objective-C/Cocoa this is done with a method 
named <code><span>dealloc</span></code>.</p>
<p>In PyObjC you should always use the <code><span>__del__</span></code> method, the <code><span>dealloc</span></code> method
can safely be ignored and the bridge will complain when you try to override
this method.</p>
<h2><a href="#id16" name="building-applications">Building applications</a></h2>
<p>There are two different ways to build applications with PyObjC. There are no
major advantages to using either one of them, use the one that is most 
convenient to you.</p>
<h3><a href="#id17" name="pure-python-buildapp-py">&quot;Pure Python&quot; :  buildapp.py</a></h3>
<p>PyObjC includes a copy of the <code><span>bundlebuilder</span></code> module. This module is
part of the Python 2.3 MacPython release and offers a way to build
distutils-style scripts for building (standalone) applications.</p>
<p>An example <code><span>buildapp.py</span></code> script:</p>
<pre>
from bundlebuilder import buildapp
buildapp(
        name = 'iClass',
        mainprogram = &quot;main.py&quot;,
        resources = [&quot;English.lproj&quot;, &quot;datasource.py&quot; ],
        nibname = &quot;MainMenu&quot;,
)   
</pre>
<p>During development you typically invoke it from the command line like this:</p>
<pre>
python buildapp.py --link build
</pre>
<p>This will build an application bundle in a folder named <code><span>build</span></code> in the
current folder. The <code><span>--link</span></code> option tells <code><span>bundlebuilder</span></code> to add symbolic
links to the application bundle instead of copies of your source and resource
files, allowing you to edit them without having to rebuild the application. To
build a standalone application, either use <code><span>--standalone</span></code> or
<code><span>--semi-standalone</span></code>. The latter will put all used modules that are not in
Python's standard library into the application bundle. The result will still
depend on an installed Python, but yields a relatively compact application.
<code><span>--standalone</span></code> will cause <code><span>bundlebuilder</span></code> to include <i>everything</i> needed
into the app bundle, including the entire Python runtime. This is useful if
you're using a different version of Python that the one that comes with MacOSX
10.2, or if you fear that a future version of OSX may come with an
incompatible Python version.</p>
<p>The online documentation for <code><span>bundlebuilder</span></code> contains more information on 
building <code><span>buildapp.py</span></code> scripts and how to invoke them. There are plenty of
example <code><span>buildapp.py</span></code> scripts in the various <a href="../Examples/00ReadMe.txt">Examples</a> subfolders.</p>
<h3><a href="#id18" name="ide-approach-xcode">&quot;IDE approach&quot; : Xcode</a></h3>
<p>PyObjC includes a number of Xcode templates that can be used to 
build (standalone) applications. Those templates are used like any other
Xcode template. The only non-obvious detail is that you have to
add your sources as resources, but Project Builder usually does the right
thing when you add a new file.</p>
<p>The templates will build an application that makes use of the installed copy
<code><span>/usr/bin/python</span></code> (e.g. the one shipped by Apple in MacOS X 10.2) and will 
copy the PyObjC modules into the application bundle. This means that this 
application bundle should be useable on any MacOS X 10.2 system.</p>
<p>See <a href="ProjectBuilder-Templates.html">the documentation for the templates</a> for more details.</p>
<p>MacOS X 10.3 seems to ship with Python 2.3 as /usr/bin/python. This means that
standalone applications build using the Project Builder templates will start
to complain about Python ABI versions in the <code><span>Console</span></code> when you run them
on MacOS X 10.3. These are harmless messages caused by the extension modules
in PyObjC.</p>
</body>
</html>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.