source: trunk/source/doc/src/objc-bridge.xml @ 8896

Last change on this file since 8896 was 8896, checked in by mikel, 12 years ago

working on objective-c bridge docs

File size: 34.8 KB
1<?xml version="1.0" encoding="utf-8"?>
2<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" ""[
3          <!ENTITY rest "<varname>&amp;rest</varname>">
4          <!ENTITY key "<varname>&amp;key</varname>">
5          <!ENTITY optional "<varname>&amp;optional</varname>">
6          <!ENTITY body "<varname>&amp;body</varname>">
7          <!ENTITY aux "<varname>&amp;aux</varname>">
8          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
9          <!ENTITY CCL "Clozure CL">
10          ]>
11<chapter id="The-Objective-C-Bridge">
12  <title>The Objective-C Bridge</title>
14  <para>Mac OS X APIs use a language called Objective-C, which is
15    approximately C with some object-oriented extensions modeled on
16    Smalltalk.  The Objective-C bridge makes it possible to work with
17    Objective-C objects and classes from Lisp, and to define classes
18    in Lisp which can be used by Objective-C.</para>
19  <para>The ultimate purpose of the Objective-C and Cocoa bridges is
20    to make Cocoa (the standard user-interface framework on Mac OS X)
21    as easy as possible to use from &CCL;, in order to support the
22    development of GUI applications and IDEs on Mac OS X (and on any
23    platform that supports Objective-C, such as GNUStep).  The
24    eventual goal, which is much closer than it used to be, is
25    complete integration of Cocoa into CLOS.</para>
26  <para>The current release provides Lisp-like syntax and naming
27    conventions for the basic Objective-C operations, with automatic type
28    processing and messages checked for validity at compile-time.  It
29    also provides some convenience facilities for working with
30    Cocoa.</para>
32  <sect1 id="Objective-C-Changes-1.2">
33    <title>Changes in 1.2</title>
35    <para>Version 1.2 of &CCL; exports most of the useful symbols
36    described in this chapter; in previous releases, most of them were
37    private in the <code>CCL</code> package.</para>
39    <para>There are several new reader macros that make it much more
40    conveinent than before to refer to several classes of symbols used
41    with the Objective-C bridge. For a full description of these
42    reader-macros, see
43    the <link linkend="anchor_Foreign-Function-Interface-Dictionary">Foreign-Function-Interface
44    Dictionary</link>, especially the entries at the beginning,
45    describing reader macros.</para>
47    <para>As in previous releases, 32-bit versions of &CCL; use 32-bit
48    floats and integers in data structures that describe geometry,
49    font sizes and metrics, and so on. 64-bit versions of &CCL; use
50    64-bit values where appropriate.</para>
52    <para>The Objective-C bridge defines the
53      type <code>NS:CGFLOAT</code> as the Lisp type of the preferred
54      floating-point type on the current platform, and defines the
55      constant <code>NS:+CGFLOAT+</code>.  On DarwinPPC32, the foreign
56      types <code>:cgfloat</code>, <code>:&lt;NSUI&gt;nteger</code>,
57      and
58      <code>:&lt;NSI&gt;nteger</code> are defined by the Objective-C
59      bridge (as 32-bit float, 32-bit unsigned integer, and 32-bit
60      signed integer, respectively); these types are defined as 64-bit
61      variants in the 64-bit interfaces.</para>
63    <para>Every Objective-C class is now properly named, either with a
64      name exported from the <code>NS</code> package (in the case of a
65      predefined class declared in the interface files) or with the
66      name provided in the <code>DEFCLASS</code> form (with <code>:METACLASS</code>
67      <code>NS:+NS-OBJECT</code>) which defines the class from Lisp.
68      The class's Lisp name is now proclaimed to be a "static"
69      variable (as if by <code>DEFSTATIC</code>, as described in the
70      <link linkend="Static_Variables">"Static Variables"
71      section</link>) and given the class object as its value.  In
72      other words:</para>
74    <programlisting>
75(send (find-class 'ns:ns-application) 'shared-application)
76    </programlisting>
78  <para>and</para>
80    <programlisting>
81(send ns:ns-application 'shared-application)
82    </programlisting>
84  <para>are equivalent.  (Since it's not legal to bind a "static"
85  variable, it may be necessary to rename some things so that
86  unrelated variables whose names coincidentally conflict with
87  Objective-C class names don't do so.)</para>
89  </sect1>
91  <sect1 id="Using-Objective-C-Classes">
92    <title>Using Objective-C Classes</title>
94    <para>The class of most standard CLOS classes is named
95      STANDARD-CLASS. In the Objective-C object model, each class is
96      an instance of a (usually unique) metaclass, which is itself an
97      instance of a "base" metaclass (often the metaclass of the class
98      named "NSObject".) So, the Objective-C class named "NSWindow"
99      and the Objective-C class "NSArray" are (sole) instances of
100      their distinct metaclasses whose names are also "NSWindow" and
101      "NSArray", respectively. (In the Objective-C world, it's much
102      more common and useful to specialize class behavior such as
103      instance allocation.)</para>
104    <para>When &CCL; first loads foreign libraries containing
105      Objective-C classes, it identifies the classes they contain. The
106      foreign class name, such as "NSWindow", is mapped to an external
107      symbol in the "NS" package via the bridge's translation rules,
108      such as NS:NS-WINDOW.  A similar transformation happens to the
109      metaclass name, with a "+" prepended, yielding something like
110      NS:+NS-WINDOW.</para>
111    <para>These classes are integrated into CLOS such that the
112      metaclass is an instance of the class OBJC:OBJC-METACLASS and
113      the class
114      is an instance of the metaclass. SLOT-DESCRIPTION metaobjects are
115      created for each instance variable, and the class and metaclass go
116      through something very similar to the "standard" CLOS class
117      initialization protocol (with a difference being that these classes
118      have already been allocated.)</para>
119    <para>Performing all this initialization, which is done when you
120      (require "COCOA"), currently takes several
121      seconds; it could conceivably be sped up some, but it's never likely
122      to be fast.</para>
123    <para>When the process is complete, CLOS is aware of several hundred
124      new Objective-C classes and their metaclasses. &CCL;'s runtime system can
125      reliably recognize MACPTRs to Objective-C classes as being CLASS objects, and
126      can (fairly reliably but heuristically) recognize instances of those
127      classes (though there are complicating factors here; see below.)
128      SLOT-VALUE can be used to access (and, with care, set) instance
129      variables in Objective-C instances. To see this, do:</para>
130    <programlisting>
131      ? (require "COCOA")
132    </programlisting>
133    <para>and, after waiting a bit longer for a Cocoa listener window to
134      appear, activate that Cocoa listener and do:</para>
135    <programlisting>? (describe (ccl::send ccl::*NSApp* 'key-window))
136    </programlisting>
137    <para>This sends a message asking for the key window, which is the window
138      that has the input focus (often the frontmost), and then describes
139      it. As we can see, NS:NS-WINDOWs have lots of interesting slots.</para>
140  </sect1>
142  <sect1 id="Instantiating-Objective-C-Objects">
143    <title>Instantiating Objective-C Objects</title>
144    <para>Making an instance of an Objective-C class (whether the class in
145      question is predefined or defined by the application) involves
146      calling MAKE-INSTANCE with the class and a set of initargs as
147      arguments.  As with STANDARD-CLASS, making an instance involves
148      initializing (with INITIALIZE-INSTANCE) an object allocated with
149      ALLOCATE-INSTANCE.</para>
150    <para>For example, you can create an ns:ns-number like this:</para>
151    <programlisting>
152      ? (make-instance 'ns:ns-number :init-with-int 42)
153      #&lt;NS-CF-NUMBER 42 (#x85962210)>
154    </programlisting>
155    <para>It's worth looking at how this would be done if you were
156      writing in Objective C:</para>
157    <programlisting>
158      [[NSNumber alloc] initWithInt: 42]
159    </programlisting>
160    <para>Allocating an instance of an Objective-C class involves sending the
161      class an "alloc" message, and then using those initargs that
162      <emphasis>don't</emphasis> correspond to slot initags as the
163      "init" message to be sent to the newly-allocated instance.  So, the
164      example above could have been done more verbosely as:</para>
165    <programlisting>
166      ? (defvar *n* (ccl::send (find-class 'ns:ns-number) 'alloc))
167      *N*
169      ? (setq *n* (ccl::send *n* :init-with-int 42))
170      #&lt;NS-CF-NUMBER 42 (#x16D340)>
171    </programlisting>
172    <para>That setq is important; this is a case where init
173      decides to replace the object and return the new one, instead
174      of modifying the existing one.
175      In fact, if you leave out the setq and
176      then try to view the value of *N*, &CCL; will freeze.  There's
177      little reason to ever do it this way; this is just to show
178      what's going on.</para>
179    <para>You've seen that an Objective-C initialization method doesn't have to
180      return the same object it was passed.  In fact, it doesn't have
181      to return any object at all; in this case, the initialization fails
182      and make-instance returns nil.</para>
183    <para>In some special cases, such as loading an ns:ns-window-controller
184      from a .nib file, it may be necessary for you to pass the
185      instance itself as one of the parameters to the initialization
186      method.  It goes like this:</para>
187    <programlisting>
188      ? (defvar *controller*
189      (make-instance 'ns:ns-window-controller))
190      *CONTROLLER*
192      ? (setq *controller*
193      (ccl::send *controller*
194      :init-with-window-nib-name #@"DataWindow"
195      :owner *controller*))
196      #&lt;NS-WINDOW-CONTROLLER &lt;NSWindowController: 0x1fb520> (#x1FB520)>
197    </programlisting>
198    <para>This example calls (make-instance) with no initargs.  When you
199      do this, the object is only allocated, and not initialized.  It
200      then sends the "init" message to do the initialization by hand.</para>
201  </sect1>
203  <sect1 id="Calling-Objective-C-Methods">
204    <title>Calling Objective-C Methods</title>
205    <para>In Objective-C, methods are called "messages", and there's
206      a special syntax to send a message to an object:</para>
207    <programlisting>
208      [w alphaValue]
209      [w setAlphaValue: 0.5]
210      [v mouse: p inRect: r]
211    </programlisting>
212    <para>The first line sends the method "alphaValue" to the object
213      <literal>w</literal>, with no parameters.  The second line sends
214      the method "setAlphaValue", with the parameter 0.5.  The third
215      line sends the method "mouse:inRect:" - yes, all one long word -
216      with the parameters <literal>p</literal> and
217      <literal>r</literal>.</para>
218    <para>In Lisp, these same three lines are:</para>
219    <programlisting>
220      (send w 'alpha-value)
221      (send w :set-alpha-value 0.5)
222      (send v :mouse p :in-rect r)
223    </programlisting>
224    <para>Notice that when a method has no parameters, its name is an ordinary
225      symbol (it doesn't matter what package the symbol is in, as
226      only its name is checked).  When a method has parameters,
227      each part of its name is a keyword, and the keywords alternate
228      with the values.</para>
229    <para>These two lines break those rules, and both  will
230      result in error messages:</para>
231    <programlisting>
232      (send w :alpha-value)
233      (send w 'set-alpha-value 0.5)
234    </programlisting>
235    <para>Instead of (send), you can also invoke (send-super), with the
236      same interface.  It has roughly the same purpose as CLOS's
237      (call-next-method); when you use (send-super), the message is
238      handled by the superclass.  This can be used to get at the
239      original implementation of a method when it is shadowed by a
240      method in your subclass.</para>
242    <sect2 id="Type-Coercion-for-ObjC-Method-Calls">
243          <title>Type Coercion for Objective-C Method Calls</title>
244      <para>&CCL;'s FFI handles many common conversions between
245        Lisp and foreign data, such as unboxing floating-point args
246        and boxing floating-point results.  The bridge adds a few more
247        automatic conversions:</para>
248      <para>NIL is equivalent to (%NULL-PTR) for any message
249        argument that requires a pointer.</para>
250      <para>T/NIL are equivalent to #$YES/#$NO for any boolean argument.</para>
251      <para>A #$YES/#$NO returned by any method that returns BOOL
252        will be automatically converted to T/NIL.</para>
253    </sect2>
255    <sect2 id="Methods-which-Return-Structures">
256          <title>Methods which Return Structures</title>
257      <para>Some Cocoa methods return small structures, such as
258        those used to represent points, rects, sizes and ranges. When
259        writing in Objective C, the compiler hides the implementation
260        details.  Unfortunately, in Lisp we must be slightly more
261        aware of them.</para>
262      <para>Methods which return structures are called in a special
263        way; the caller allocates space for the result, and passes a
264        pointer to it as an extra argument to the method.  This is
265        called a Structure Return, or STRET.  Don't look at me; I
266        don't name these things.</para>
267      <para>Here's a simple use of this in Objective C.  The first line
268            sends the "bounds" message to v1, which returns a rectangle.
269            The second line sends the "setBounds" message to v2, passing
270            that same rectangle as a parameter.</para>
271      <programlisting>
272        NSRect r = [v1 bounds];
273        [v2 setBounds r];
274          </programlisting>
275      <para>In Lisp, we must explicitly allocate the memory, which
276        is done most easily and safely with <xref linkend="m_rlet"/>.
277        We do it like this:</para>
278      <programlisting>
279(rlet ((r :&lt;NSR&gt;ect))
280          (send/stret r v1 'bounds)
281          (send v2 :set-bounds r))
282      </programlisting>
283      <para>The rlet allocates the storage (but doesn't initialize
284        it), and makes sure that it will be deallocated when we're
285        done.  It binds the variable r to refer to it.  The call to
286        <literal>send/stret</literal> is just like an ordinary call to
287        <literal>send</literal>, except that r is passed as an extra,
288        first parameter.  The third line, which calls
289        <literal>send</literal>, does not need to do anything special,
290        because there's nothing complicated about passing a structure
291        as a parameter.</para>
292          <para>In order to make STRETs easier to use, the bridge
293            provides two conveniences.</para>
294      <para>First, you can use the macros <literal>slet</literal>
295        and <literal>slet*</literal> to allocate and initialize local
296        variables to foreign structures in one step.  The example
297        above could have been written more tersely as:</para>
298      <programlisting>
299(slet ((r (send v1 'bounds)))
300      (send v2 :set-bounds r))
301          </programlisting>
302      <para>Second, when one call to <literal>send</literal> is made
303        inside another, the inner one has an implicit
304        <literal>slet</literal> around it.  So, one could in fact
305        just write:</para>
306      <programlisting>
307(send v1 :set-bounds (send v2 'bounds))
308      </programlisting>
309      <para>There are also several psuedo-functions provided for convenience
310        by the Objective-C compiler, to make objects of specific types. The
311        following are currently supported by the bridge: NS-MAKE-POINT,
312        NS-MAKE-RANGE, NS-MAKE-RECT, and NS-MAKE-SIZE.</para>
313      <para>These pseudo-functions can be used within an SLET initform:</para>
314      <programlisting>
315(slet ((p (ns-make-point 100.0 200.0)))
316      (send w :set-frame-origin p))
317      </programlisting>
318      <para>Or within a call to <literal>send</literal>:</para>
319      <programlisting>
320(send w :set-origin (ns-make-point 100.0 200.0))
321      </programlisting>
322      <para>However, since these aren't real functions, a call like the
323        following won't work:</para>
324      <programlisting>
325(setq p (ns-make-point 100.0 200.0))
326      </programlisting>
327      <para>To extract fields from these objects, there are also some
328        convenience macros: NS-MAX-RANGE, NS-MIN-X,
329        NS-MIN-Y, NS-MAX-X, NS-MAX-Y, NS-MID-X, NS-MID-Y,
330        NS-HEIGHT, and NS-WIDTH.</para>
331      <para>Note that there is also a <literal>send-super/stret</literal>
332        for use within methods.  Like <literal>send-super</literal>,
333        it ignores any shadowing methods in a subclass, and calls the
334        version of a method which belongs to its superclass.</para>
335    </sect2>
337    <sect2 id="Variable-Arity-Messages">
338          <title>Variable-Arity Messages</title>
339      <para>
340        There are a few messages in Cocoa which take variable numbers
341        of arguments. Perhaps the most common examples involve
342        formatted strings:</para>
343      <programlisting>
344[NSClass stringWithFormat: "%f %f" x y]
345      </programlisting>
346      <para>In Lisp, this would be written:</para>
347      <programlisting>
348(send (find-class 'ns:ns-string)
349      :string-with-format #@"%f %f"
350      (:double-float x :double-float y))
351      </programlisting>
352      <para>Note that it's necessary to specify the foreign types of the
353        variables (in this example, :double-float), because the
354        compiler has no general way of knowing these types.  (You
355        might think that it could parse the format string, but this
356        would only work for format strings which are not determined
357        at runtime.)</para>
358      <para>Because the Objective-C runtime system does not provide any information
359        on which messages are variable arity, they must be explicitly
360        declared. The standard variable arity messages in Cocoa are
361        predeclared by the bridge.  If you need to declare a new
362        variable arity message, use
363        (DEFINE-VARIABLE-ARITY-MESSAGE "myVariableArityMessage:").</para>
364    </sect2>
366    <sect2 id="Optimization">
367          <title>Optimization</title>
368      <para>The bridge works fairly hard to optimize message sends,
369        when it has enough information to do so.  There are two cases
370        when it does.  In either, a message send should be nearly as
371        efficient as when writing in Objective C.</para>
372      <para>The first case is when both the message and the
373        receiver's class are known at compile-time. In general, the
374        only way the receiver's class is known is if you declare it,
375        which you can do with either a DECLARE or a THE form.  For
376        example:</para>
377      <programlisting>
378(send (the ns:ns-window w) 'center)
379          </programlisting>
380      <para>Note that there is no way in Objective-C to name the class of a
381        class.  Thus the bridge provides a declaration, @METACLASS.
382        The type of an instance of "NSColor" is ns:ns-color.  The type
383        of the <emphasis>class</emphasis> "NSColor" is (@metaclass
384        ns:ns-color):</para>
385      <programlisting>
386(let ((c (find-class 'ns:ns-color)))
387  (declare ((ccl::@metaclass ns:ns-color) c))
388  (send c 'white-color))
389      </programlisting>
390      <para>The other case that allows optimization is when only
391        the message is known at compile-time, but its type signature
392        is unique. Of the more-than-6000 messages currently provided
393        by Cocoa, only about 50 of them have nonunique type
394        signatures.</para>
395      <para>An example of a message with a type signature that is
396        not unique is SET.  It returns VOID for NSColor, but ID for
397        NSSet.  In order to optimize sends of messages with nonunique
398        type signatures, the class of the receiver must be declared at
399        compile-time.</para>
400      <para>If the type signature is nonunique or the message is
401        unknown at compile-time, then a slower runtime call must be
402        used.</para>
403      <para>When the receiver's class is unknown, the bridge's
404        ability to optimize relies on a type-signature table which it
405        maintains.  When first loaded, the bridge initializes this
406        table by scanning every method of every Objective-C class.  When new
407        methods are defined later, the table must be updated.  This
408        happens automatically when you define methods in Lisp.  After
409        any other major change, such as loading an external framework,
410        you should rebuild the table:</para>
411      <programlisting>
412? (update-type-signatures)
413      </programlisting>
414      <para>Because <literal>send</literal> and its relatives
415        <literal>send-super</literal>, <literal>send/stret</literal>,
416        and <literal>send-super/stret</literal> are macros, they
417        cannot be <literal>funcall</literal>ed,
418        <literal>apply</literal>ed, or passed as arguments to
419        functions.</para>
420      <para>To work around this, there are function equivalents to
421        them: <literal>%send</literal>,
422        <literal>%send-super</literal>,
423        <literal>%send/stret</literal>, and
424        <literal>%send-super/stret</literal>.  However, these
425        functions should be used only when the macros will not do,
426        because they are unable to optimize.</para>
427    </sect2>
428  </sect1>
430  <sect1 id="Defining-Objective-C-Classes">
431    <title>Defining Objective-C Classes</title>
432    <para>You can define your own foreign classes, which can then be
433      passed to foreign functions; the methods which you implement in
434      Lisp will be made available to the foreign code as
435      callbacks.</para>
436    <para>You can also define subclasses of existing classes,
437      implementing your subclass in Lisp even though the parent class
438      was in Objective C.  One such subclass is CCL::NS-LISP-STRING.
439      It is also particularly useful to make subclasses of
440      NS-WINDOW-CONTROLLER.</para>
441    <para>We can use the MOP to define new Objective-C classes, but
442      we have to do something a little funny: the :METACLASS that we'd
443      want to use in a DEFCLASS option generally doesn't exist until
444      we've created the class (recall that Objective-C classes have, for the
445      sake of argument, unique and private metaclasses.) We can sort
446      of sleaze our way around this by specifying a known Objective-C
447      metaclass object name as the value of the DEFCLASS :METACLASS
448      object; the metaclass of the root class NS:NS-OBJECT,
449      NS:+NS-OBJECT, makes a good choice. To make a subclass of
450      NS:NS-WINDOW (that, for simplicity's sake, doesn't define any
451      new slots), we could do:</para>
452    <programlisting>
453(defclass example-window (ns:ns-window)
454  ()
455  (:metaclass ns:+ns-object))
456    </programlisting>
457    <para>That'll create a new Objective-C class named EXAMPLE-WINDOW whose
458      metaclass is the class named +EXAMPLE-WINDOW. The class will be
459      an object of type OBJC:OBJC-CLASS, and the metaclass will be of
460      type OBJC:OBJC-METACLASS.  EXAMPLE-WINDOW will be a subclass of
461      NS-WINDOW.</para>
463    <sect2 id="Defining-classes-with-foreign-slots">
464          <title>Defining classes with foreign slots</title>
465      <para>If a slot specification in an Objective-C class
466        definition contains the keyword :FOREIGN-TYPE, the slot will
467        be a "foreign slot" (i.e. an Objective-C instance variable). Be aware
468        that it is an error to redefine an Objective-C class so that its
469        foreign slots change in any way, and &CCL; doesn't do
470        anything consistent when you try to.</para>
471      <para>The value of the :FOREIGN-TYPE initarg should be a
472        foreign type specifier. For example, if we wanted (for some
473        reason) to define a subclass of NS:NS-WINDOW that kept track
474        of the number of key events it had received (and needed an
475        instance variable to keep that information in), we could
476        say:</para>
477      <programlisting>
478(defclass key-event-counting-window (ns:ns-window)
479  ((key-event-count :foreign-type :int
480                    :initform 0
481                    :accessor window-key-event-count))
482  (:metaclass ns:+ns-object))
483      </programlisting>
484      <para>Foreign slots are always SLOT-BOUNDP, and the initform
485        above is redundant: foreign slots are initialized to binary
486        0.</para>
487    </sect2>
489    <sect2 id="Defining-classes-with-Lisp-slots">
490          <title>Defining classes with Lisp slots</title>
491      <para>A slot specification in an Objective-C class definition that
492        doesn't contain the :FOREIGN-TYPE initarg defines a
493        pretty-much normal lisp slot that'll happen to be associated
494        with "an instance of a foreign class". For instance:</para>
495      <programlisting>
496(defclass hemlock-buffer-string (ns:ns-string)
497  ((hemlock-buffer :type hi::hemlock-buffer
498                   :initform hi::%make-hemlock-buffer
499                   :accessor string-hemlock-buffer))
500  (:metaclass ns:+ns-object))
501          </programlisting>
502      <para>As one might expect, this has memory-management
503        implications: we have to maintain an association between a
504        MACPTR and a set of lisp objects (its slots) as long as the
505        Objective-C instance exists, and we have to ensure that the Objective-C
506        instance exists (does not have its -dealloc method called)
507        while lisp is trying to think of it as a first-class object
508        that can't be "deallocated" while it's still possible to
509        reference it. Associating one or more lisp objects with a
510        foreign instance is something that's often very useful; if you
511        were to do this "by hand", you'd have to face many of the same
512        memory-management issues.</para>
513    </sect2>
514  </sect1>
516  <sect1 id="Defining-Objective-C-Methods">
517    <title>Defining Objective-C Methods</title>
518    <para>In Objective-C, unlike in CLOS, every method belongs to some
519      particular class.  This is probably not a strange concept to
520      you, because C++ and Java do the same thing.  When you use Lisp
521      to define Objective-C methods, it is only possible to define methods
522      belonging to Objective-C classes which have been defined in
523      Lisp.</para>
524    <para>The macro <literal>define-objc-method</literal> is used for
525      this.  As described in the
526      section <link linkend="Calling-Objective-C-Methods">Calling
527      Objective-C Methods</link>, the names of Objective-C methods are
528      broken into pieces, each piece followed by a parameter.  The
529      types of all parameters must be explicitly declared.</para>
530    <para>Right now, I'm not sure how to formally describe the usage
531      of define-objc-method, so I'm going to do it with some short
532      examples.  Let us define a class to use in them:</para>
533    <programlisting>
534(defclass data-window-controller (ns:ns-window-controller)
535  ((window :foreign-type :id :accessor window)
536   (data :initform nil :accessor data))
537  (:metaclass ns:+ns-object))
538    </programlisting>
539    <para>There's nothing special about this class.  It inherits
540      from ns:ns-window-controller.  It has two slots:
541      <literal>window</literal> is a foreign slot, stored in the Objective-C
542      world; and <literal>data</literal> is an ordinary slot, stored
543      in the Lisp world.</para>
544    <para>Here is an example of how to define a method which takes no
545      arguments:</para>
546    <programlisting>
547(define-objc-method ((:id get-window)
548                     data-window-controller)
549    (window self))
550    </programlisting>
551    <para>The return type of this method is the foreign type :id,
552      which is used for all Objective-C objects.  The name of the method is
553      <literal>get-window</literal>.  The body of the method is the
554      single line (window self).  The variable <literal>self</literal>
555      is bound, within the body, to the instance which is receiving
556      the message.  The call to <literal>window</literal> uses the
557      CLOS accessor to get the value of the window field.</para>
558    <para>Here's an example which takes a parameter.  Notice that
559      the name of the method without a parameter was an ordinary
560      symbol, but with a parameter, it's a keyword:</para>
561    <programlisting>
562(define-objc-method ((:id :init-with-multiplier (:int multiplier))
563                     data-window-controller)
564  (setf (data self) (make-array 100))
565  (dotimes (i 100)
566    (setf (aref (data self) i)
567          (* i multiplier)))
568  self)
569    </programlisting>
570    <para>To Objective-C code which uses the class, the name of this
571      method is "initWithMultiplier:".  The name of the parameter is
572      <literal>multiplier</literal>, and its type is :int.  The body
573      of the method does some meaningless things.  Then it returns
574      <literal>self</literal>, because this is an initialization
575      method.</para>
576    <para>Here's an example with more than one parameter:</para>
577    <programlisting>
578(define-objc-method ((:id :init-with-multiplier (:int multiplier)
579                          :and-addend (:int addend))
580                     data-window-controller)
581  (setf (data self) (make-array size))
582  (dotimes (i 100)
583    (setf (aref (data self) i)
584          (+ (* i multiplier)
585             addend)))
586  self)
587    </programlisting>
588    <para>To Objective-C, the name of this method is
589      "initWithMultiplier:andAddend:".  Both parameters are of type
590      :int; the first is named <literal>multiplier</literal>, and the
591      second is <literal>addend</literal>.  Again, the method returns
592      <literal>self</literal>.</para>
593    <para>Here is a method which does not return any value, a
594      so-called "void method".  Where our other methods said :id, this
595      one says :void for the return type:</para>
596    <programlisting>
597(define-objc-method ((:void :take-action (:id sender))
598                     data-window-controller)
599  (declare (ignore sender))
600  (dotimes (i 100)
601    (setf (aref (data self) i)
602          (- (aref (data self) i)))))
603    </programlisting>
604    <para>This method would be called "takeAction:" in Objective-C.  The
605      convention for methods that are going to be used as Cocoa
606      actions is that they take one parameter, which is the object
607      responsible for triggering the action.  However, this method
608      doesn't actually need to use that parameter, so it explicitly
609      ignores it to avoid a compiler warning.  As promised, the method
610      doesn't return any value.</para>
611    <para>There is also an alternate syntax, illustrated here.  The
612      following two method definitions are equivalent:</para>
613    <programlisting>
614(define-objc-method ("applicationShouldTerminate:"
615                     "LispApplicationDelegate")
616    (:id sender :&lt;BOOL>)
617    (declare (ignore sender))
618    nil)
620(define-objc-method ((:&lt;BOOL>
621                        :application-should-terminate sender)
622                       lisp-application-delegate)
623    (declare (ignore sender))
624    nil)
625    </programlisting>
626    <sect2 id="Method-Redefinition-Constraints">
627          <title>Method Redefinition Constraints</title>
628      <para>Objective C was not designed, as Lisp was, with runtime
629        redefinition in mind.  So, there are a few constraints about
630        how and when you can replace the definition of an Objective C
631        method.  Currently, if you break these rules, nothing will
632        collapse, but the behaviour will be confusing; so
633        don't.</para>
634      <para>Objective C methods can be redefined at runtime, but
635        their signatures shouldn't change.  That is, the types of the
636        arguments and the return type have to stay the same.  The
637        reason for this is that changing the signature changes the
638        selector which is used to call the method.</para>
639      <para>When a method has already been defined in one class, and
640        you define it in a subclass, shadowing the original method,
641        they must both have the same type signature.  There is no such
642        constraint, though, if the two classes aren't related and the
643        methods just happen to have the same name.</para>
644    </sect2>
645  </sect1>
647  <sect1 id="How-Objective-C-Names-are-Mapped-to-Lisp-Symbols">
648    <title>How Objective-C Names are Mapped to Lisp Symbols</title>
649    <para>There is a standard set of naming conventions for Cocoa
650      classes, messages, etc.  As long as they are followed, the
651      bridge is fairly good at automaticallly translating between Objective-C
652      and Lisp names.</para>
653    <para>For example, "NSOpenGLView" becomes ns:ns-opengl-view;
654      "NSURLHandleClient" becomes ns:ns-url-handle-client; and
655      "nextEventMatchingMask:untilDate:inMode:dequeue:" becomes
656      (:next-event-matching-mask :until-date :in-mode :dequeue).  What
657      a mouthful.</para>
658    <para>To see how a given Objective-C or Lisp name will be translated by
659      the bridge, you can use the following functions:</para>
660        <simplelist type="vert">
661          <member>(ccl::objc-to-lisp-classname string)</member>
662          <member>(ccl::lisp-to-objc-classname symbol)</member>
663          <member>(ccl::objc-to-lisp-message string)</member>
664          <member>(ccl::lisp-to-objc-message string)</member>
665          <member>(ccl::objc-to-lisp-init string)</member>
666          <member>(ccl::lisp-to-objc-init keyword-list)</member>
667        </simplelist>
669    <para>Of course, there will always be exceptions to any naming
670      convention.  Please tell us on the mailing lists if you come
671      across any name translation problems that seem to be bugs.
672      Otherwise, the bridge provides two ways of dealing with
673      exceptions:</para>
674    <para>First, you can pass a string as the class name of
675      MAKE-OBJC-INSTANCE and as the message to SEND.  These strings
676      will be directly interpreted as Objective-C names, with no
677      translation. This is useful for a one-time exception.  For
678      example:</para>
679    <programlisting>
680(ccl::make-objc-instance "WiErDclass")
681(ccl::send o "WiErDmEsSaGe:WithARG:" x y)
682    </programlisting>
683    <para>Alternatively, you can define a special translation rule
684      for your exception.  This is useful for an exceptional name that
685      you need to use througout your code.  Some examples:</para>
686    <programlisting>
687(ccl::define-classname-translation "WiErDclass" wierd-class)
688(ccl::define-message-translation "WiErDmEsSaGe:WithARG:" (:weird-message :with-arg))
689(ccl::define-init-translation "WiErDiNiT:WITHOPTION:" (:weird-init :option))
690    </programlisting>
691    <para>The normal rule in Objective-C names is that each word begins with a
692      capital letter (except possibly the first).  Using this rule
693      literally, "NSWindow" would be translated as N-S-WINDOW, which
694      seems wrong.  "NS" is a special word in Objective-C that should not be
695      broken at each capital letter. Likewise "URL", "PDF", "OpenGL",
696      etc. Most common special words used in Cocoa are already defined
697      in the bridge, but you can define new ones as follows:</para>
698    <programlisting>
699(ccl::define-special-objc-word "QuickDraw")
700    </programlisting>
701    <para>Note that message keywords in a SEND such as (SEND V
702      :MOUSE P :IN-RECT R) may look like the keyword arguments in a
703      Lisp function call, but they really aren't. All keywords must be
704      present and the order is significant. Neither (:IN-RECT :MOUSE)
705      nor (:MOUSE) translate to "mouse:inRect:"</para>
706    <para>Also, as a special exception, an "init" prefix is optional
707      in the initializer keywords, so (MAKE-OBJC-INSTANCE 'NS-NUMBER
708      :INIT-WITH-FLOAT 2.7) can also be expressed as
710  </sect1>
Note: See TracBrowser for help on using the repository browser.