1211 lines
42 KiB
Plaintext
1211 lines
42 KiB
Plaintext
@c Copyright (C) 1988-2021 Free Software Foundation, Inc.
|
|
@c This is part of the GCC manual.
|
|
@c For copying conditions, see the file gcc.texi.
|
|
|
|
@node Objective-C
|
|
@comment node-name, next, previous, up
|
|
|
|
@chapter GNU Objective-C Features
|
|
|
|
This document is meant to describe some of the GNU Objective-C
|
|
features. It is not intended to teach you Objective-C. There are
|
|
several resources on the Internet that present the language.
|
|
|
|
@menu
|
|
* GNU Objective-C runtime API::
|
|
* Executing code before main::
|
|
* Type encoding::
|
|
* Garbage Collection::
|
|
* Constant string objects::
|
|
* compatibility_alias::
|
|
* Exceptions::
|
|
* Synchronization::
|
|
* Fast enumeration::
|
|
* Messaging with the GNU Objective-C runtime::
|
|
@end menu
|
|
|
|
@c =========================================================================
|
|
@node GNU Objective-C runtime API
|
|
@section GNU Objective-C Runtime API
|
|
|
|
This section is specific for the GNU Objective-C runtime. If you are
|
|
using a different runtime, you can skip it.
|
|
|
|
The GNU Objective-C runtime provides an API that allows you to
|
|
interact with the Objective-C runtime system, querying the live
|
|
runtime structures and even manipulating them. This allows you for
|
|
example to inspect and navigate classes, methods and protocols; to
|
|
define new classes or new methods, and even to modify existing classes
|
|
or protocols.
|
|
|
|
If you are using a ``Foundation'' library such as GNUstep-Base, this
|
|
library will provide you with a rich set of functionality to do most
|
|
of the inspection tasks, and you probably will only need direct access
|
|
to the GNU Objective-C runtime API to define new classes or methods.
|
|
|
|
@menu
|
|
* Modern GNU Objective-C runtime API::
|
|
* Traditional GNU Objective-C runtime API::
|
|
@end menu
|
|
|
|
@c =========================================================================
|
|
@node Modern GNU Objective-C runtime API
|
|
@subsection Modern GNU Objective-C Runtime API
|
|
|
|
The GNU Objective-C runtime provides an API which is similar to the
|
|
one provided by the ``Objective-C 2.0'' Apple/NeXT Objective-C
|
|
runtime. The API is documented in the public header files of the GNU
|
|
Objective-C runtime:
|
|
|
|
@itemize @bullet
|
|
|
|
@item
|
|
@file{objc/objc.h}: this is the basic Objective-C header file,
|
|
defining the basic Objective-C types such as @code{id}, @code{Class}
|
|
and @code{BOOL}. You have to include this header to do almost
|
|
anything with Objective-C.
|
|
|
|
@item
|
|
@file{objc/runtime.h}: this header declares most of the public runtime
|
|
API functions allowing you to inspect and manipulate the Objective-C
|
|
runtime data structures. These functions are fairly standardized
|
|
across Objective-C runtimes and are almost identical to the Apple/NeXT
|
|
Objective-C runtime ones. It does not declare functions in some
|
|
specialized areas (constructing and forwarding message invocations,
|
|
threading) which are in the other headers below. You have to include
|
|
@file{objc/objc.h} and @file{objc/runtime.h} to use any of the
|
|
functions, such as @code{class_getName()}, declared in
|
|
@file{objc/runtime.h}.
|
|
|
|
@item
|
|
@file{objc/message.h}: this header declares public functions used to
|
|
construct, deconstruct and forward message invocations. Because
|
|
messaging is done in quite a different way on different runtimes,
|
|
functions in this header are specific to the GNU Objective-C runtime
|
|
implementation.
|
|
|
|
@item
|
|
@file{objc/objc-exception.h}: this header declares some public
|
|
functions related to Objective-C exceptions. For example functions in
|
|
this header allow you to throw an Objective-C exception from plain
|
|
C/C++ code.
|
|
|
|
@item
|
|
@file{objc/objc-sync.h}: this header declares some public functions
|
|
related to the Objective-C @code{@@synchronized()} syntax, allowing
|
|
you to emulate an Objective-C @code{@@synchronized()} block in plain
|
|
C/C++ code.
|
|
|
|
@item
|
|
@file{objc/thr.h}: this header declares a public runtime API threading
|
|
layer that is only provided by the GNU Objective-C runtime. It
|
|
declares functions such as @code{objc_mutex_lock()}, which provide a
|
|
platform-independent set of threading functions.
|
|
|
|
@end itemize
|
|
|
|
The header files contain detailed documentation for each function in
|
|
the GNU Objective-C runtime API.
|
|
|
|
@c =========================================================================
|
|
@node Traditional GNU Objective-C runtime API
|
|
@subsection Traditional GNU Objective-C Runtime API
|
|
|
|
The GNU Objective-C runtime used to provide a different API, which we
|
|
call the ``traditional'' GNU Objective-C runtime API. Functions
|
|
belonging to this API are easy to recognize because they use a
|
|
different naming convention, such as @code{class_get_super_class()}
|
|
(traditional API) instead of @code{class_getSuperclass()} (modern
|
|
API). Software using this API includes the file
|
|
@file{objc/objc-api.h} where it is declared.
|
|
|
|
Starting with GCC 4.7.0, the traditional GNU runtime API is no longer
|
|
available.
|
|
|
|
@c =========================================================================
|
|
@node Executing code before main
|
|
@section @code{+load}: Executing Code before @code{main}
|
|
|
|
This section is specific for the GNU Objective-C runtime. If you are
|
|
using a different runtime, you can skip it.
|
|
|
|
The GNU Objective-C runtime provides a way that allows you to execute
|
|
code before the execution of the program enters the @code{main}
|
|
function. The code is executed on a per-class and a per-category basis,
|
|
through a special class method @code{+load}.
|
|
|
|
This facility is very useful if you want to initialize global variables
|
|
which can be accessed by the program directly, without sending a message
|
|
to the class first. The usual way to initialize global variables, in the
|
|
@code{+initialize} method, might not be useful because
|
|
@code{+initialize} is only called when the first message is sent to a
|
|
class object, which in some cases could be too late.
|
|
|
|
Suppose for example you have a @code{FileStream} class that declares
|
|
@code{Stdin}, @code{Stdout} and @code{Stderr} as global variables, like
|
|
below:
|
|
|
|
@smallexample
|
|
|
|
FileStream *Stdin = nil;
|
|
FileStream *Stdout = nil;
|
|
FileStream *Stderr = nil;
|
|
|
|
@@implementation FileStream
|
|
|
|
+ (void)initialize
|
|
@{
|
|
Stdin = [[FileStream new] initWithFd:0];
|
|
Stdout = [[FileStream new] initWithFd:1];
|
|
Stderr = [[FileStream new] initWithFd:2];
|
|
@}
|
|
|
|
/* @r{Other methods here} */
|
|
@@end
|
|
|
|
@end smallexample
|
|
|
|
In this example, the initialization of @code{Stdin}, @code{Stdout} and
|
|
@code{Stderr} in @code{+initialize} occurs too late. The programmer can
|
|
send a message to one of these objects before the variables are actually
|
|
initialized, thus sending messages to the @code{nil} object. The
|
|
@code{+initialize} method which actually initializes the global
|
|
variables is not invoked until the first message is sent to the class
|
|
object. The solution would require these variables to be initialized
|
|
just before entering @code{main}.
|
|
|
|
The correct solution of the above problem is to use the @code{+load}
|
|
method instead of @code{+initialize}:
|
|
|
|
@smallexample
|
|
|
|
@@implementation FileStream
|
|
|
|
+ (void)load
|
|
@{
|
|
Stdin = [[FileStream new] initWithFd:0];
|
|
Stdout = [[FileStream new] initWithFd:1];
|
|
Stderr = [[FileStream new] initWithFd:2];
|
|
@}
|
|
|
|
/* @r{Other methods here} */
|
|
@@end
|
|
|
|
@end smallexample
|
|
|
|
The @code{+load} is a method that is not overridden by categories. If a
|
|
class and a category of it both implement @code{+load}, both methods are
|
|
invoked. This allows some additional initializations to be performed in
|
|
a category.
|
|
|
|
This mechanism is not intended to be a replacement for @code{+initialize}.
|
|
You should be aware of its limitations when you decide to use it
|
|
instead of @code{+initialize}.
|
|
|
|
@menu
|
|
* What you can and what you cannot do in +load::
|
|
@end menu
|
|
|
|
|
|
@node What you can and what you cannot do in +load
|
|
@subsection What You Can and Cannot Do in @code{+load}
|
|
|
|
@code{+load} is to be used only as a last resort. Because it is
|
|
executed very early, most of the Objective-C runtime machinery will
|
|
not be ready when @code{+load} is executed; hence @code{+load} works
|
|
best for executing C code that is independent on the Objective-C
|
|
runtime.
|
|
|
|
The @code{+load} implementation in the GNU runtime guarantees you the
|
|
following things:
|
|
|
|
@itemize @bullet
|
|
|
|
@item
|
|
you can write whatever C code you like;
|
|
|
|
@item
|
|
you can allocate and send messages to objects whose class is implemented
|
|
in the same file;
|
|
|
|
@item
|
|
the @code{+load} implementation of all super classes of a class are
|
|
executed before the @code{+load} of that class is executed;
|
|
|
|
@item
|
|
the @code{+load} implementation of a class is executed before the
|
|
@code{+load} implementation of any category.
|
|
|
|
@end itemize
|
|
|
|
In particular, the following things, even if they can work in a
|
|
particular case, are not guaranteed:
|
|
|
|
@itemize @bullet
|
|
|
|
@item
|
|
allocation of or sending messages to arbitrary objects;
|
|
|
|
@item
|
|
allocation of or sending messages to objects whose classes have a
|
|
category implemented in the same file;
|
|
|
|
@item
|
|
sending messages to Objective-C constant strings (@code{@@"this is a
|
|
constant string"});
|
|
|
|
@end itemize
|
|
|
|
You should make no assumptions about receiving @code{+load} in sibling
|
|
classes when you write @code{+load} of a class. The order in which
|
|
sibling classes receive @code{+load} is not guaranteed.
|
|
|
|
The order in which @code{+load} and @code{+initialize} are called could
|
|
be problematic if this matters. If you don't allocate objects inside
|
|
@code{+load}, it is guaranteed that @code{+load} is called before
|
|
@code{+initialize}. If you create an object inside @code{+load} the
|
|
@code{+initialize} method of object's class is invoked even if
|
|
@code{+load} was not invoked. Note if you explicitly call @code{+load}
|
|
on a class, @code{+initialize} will be called first. To avoid possible
|
|
problems try to implement only one of these methods.
|
|
|
|
The @code{+load} method is also invoked when a bundle is dynamically
|
|
loaded into your running program. This happens automatically without any
|
|
intervening operation from you. When you write bundles and you need to
|
|
write @code{+load} you can safely create and send messages to objects whose
|
|
classes already exist in the running program. The same restrictions as
|
|
above apply to classes defined in bundle.
|
|
|
|
|
|
|
|
@node Type encoding
|
|
@section Type Encoding
|
|
|
|
This is an advanced section. Type encodings are used extensively by
|
|
the compiler and by the runtime, but you generally do not need to know
|
|
about them to use Objective-C.
|
|
|
|
The Objective-C compiler generates type encodings for all the types.
|
|
These type encodings are used at runtime to find out information about
|
|
selectors and methods and about objects and classes.
|
|
|
|
The types are encoded in the following way:
|
|
|
|
@c @sp 1
|
|
|
|
@multitable @columnfractions .25 .75
|
|
@item @code{_Bool}
|
|
@tab @code{B}
|
|
@item @code{char}
|
|
@tab @code{c}
|
|
@item @code{unsigned char}
|
|
@tab @code{C}
|
|
@item @code{short}
|
|
@tab @code{s}
|
|
@item @code{unsigned short}
|
|
@tab @code{S}
|
|
@item @code{int}
|
|
@tab @code{i}
|
|
@item @code{unsigned int}
|
|
@tab @code{I}
|
|
@item @code{long}
|
|
@tab @code{l}
|
|
@item @code{unsigned long}
|
|
@tab @code{L}
|
|
@item @code{long long}
|
|
@tab @code{q}
|
|
@item @code{unsigned long long}
|
|
@tab @code{Q}
|
|
@item @code{float}
|
|
@tab @code{f}
|
|
@item @code{double}
|
|
@tab @code{d}
|
|
@item @code{long double}
|
|
@tab @code{D}
|
|
@item @code{void}
|
|
@tab @code{v}
|
|
@item @code{id}
|
|
@tab @code{@@}
|
|
@item @code{Class}
|
|
@tab @code{#}
|
|
@item @code{SEL}
|
|
@tab @code{:}
|
|
@item @code{char*}
|
|
@tab @code{*}
|
|
@item @code{enum}
|
|
@tab an @code{enum} is encoded exactly as the integer type that the compiler uses for it, which depends on the enumeration
|
|
values. Often the compiler users @code{unsigned int}, which is then encoded as @code{I}.
|
|
@item unknown type
|
|
@tab @code{?}
|
|
@item Complex types
|
|
@tab @code{j} followed by the inner type. For example @code{_Complex double} is encoded as "jd".
|
|
@item bit-fields
|
|
@tab @code{b} followed by the starting position of the bit-field, the type of the bit-field and the size of the bit-field (the bit-fields encoding was changed from the NeXT's compiler encoding, see below)
|
|
@end multitable
|
|
|
|
@c @sp 1
|
|
|
|
The encoding of bit-fields has changed to allow bit-fields to be
|
|
properly handled by the runtime functions that compute sizes and
|
|
alignments of types that contain bit-fields. The previous encoding
|
|
contained only the size of the bit-field. Using only this information
|
|
it is not possible to reliably compute the size occupied by the
|
|
bit-field. This is very important in the presence of the Boehm's
|
|
garbage collector because the objects are allocated using the typed
|
|
memory facility available in this collector. The typed memory
|
|
allocation requires information about where the pointers are located
|
|
inside the object.
|
|
|
|
The position in the bit-field is the position, counting in bits, of the
|
|
bit closest to the beginning of the structure.
|
|
|
|
The non-atomic types are encoded as follows:
|
|
|
|
@c @sp 1
|
|
|
|
@multitable @columnfractions .2 .8
|
|
@item pointers
|
|
@tab @samp{^} followed by the pointed type.
|
|
@item arrays
|
|
@tab @samp{[} followed by the number of elements in the array followed by the type of the elements followed by @samp{]}
|
|
@item structures
|
|
@tab @samp{@{} followed by the name of the structure (or @samp{?} if the structure is unnamed), the @samp{=} sign, the type of the members and by @samp{@}}
|
|
@item unions
|
|
@tab @samp{(} followed by the name of the structure (or @samp{?} if the union is unnamed), the @samp{=} sign, the type of the members followed by @samp{)}
|
|
@item vectors
|
|
@tab @samp{![} followed by the vector_size (the number of bytes composing the vector) followed by a comma, followed by the alignment (in bytes) of the vector, followed by the type of the elements followed by @samp{]}
|
|
@end multitable
|
|
|
|
Here are some types and their encodings, as they are generated by the
|
|
compiler on an i386 machine:
|
|
|
|
@sp 1
|
|
|
|
@multitable @columnfractions .60 .40
|
|
@item Objective-C type
|
|
@tab Compiler encoding
|
|
@item
|
|
@smallexample
|
|
int a[10];
|
|
@end smallexample
|
|
@tab @code{[10i]}
|
|
@item
|
|
@smallexample
|
|
struct @{
|
|
int i;
|
|
float f[3];
|
|
int a:3;
|
|
int b:2;
|
|
char c;
|
|
@}
|
|
@end smallexample
|
|
@tab @code{@{?=i[3f]b128i3b131i2c@}}
|
|
@item
|
|
@smallexample
|
|
int a __attribute__ ((vector_size (16)));
|
|
@end smallexample
|
|
@tab @code{![16,16i]} (alignment depends on the machine)
|
|
@end multitable
|
|
|
|
@sp 1
|
|
|
|
In addition to the types the compiler also encodes the type
|
|
specifiers. The table below describes the encoding of the current
|
|
Objective-C type specifiers:
|
|
|
|
@sp 1
|
|
|
|
@multitable @columnfractions .25 .75
|
|
@item Specifier
|
|
@tab Encoding
|
|
@item @code{const}
|
|
@tab @code{r}
|
|
@item @code{in}
|
|
@tab @code{n}
|
|
@item @code{inout}
|
|
@tab @code{N}
|
|
@item @code{out}
|
|
@tab @code{o}
|
|
@item @code{bycopy}
|
|
@tab @code{O}
|
|
@item @code{byref}
|
|
@tab @code{R}
|
|
@item @code{oneway}
|
|
@tab @code{V}
|
|
@end multitable
|
|
|
|
@sp 1
|
|
|
|
The type specifiers are encoded just before the type. Unlike types
|
|
however, the type specifiers are only encoded when they appear in method
|
|
argument types.
|
|
|
|
Note how @code{const} interacts with pointers:
|
|
|
|
@sp 1
|
|
|
|
@multitable @columnfractions .25 .75
|
|
@item Objective-C type
|
|
@tab Compiler encoding
|
|
@item
|
|
@smallexample
|
|
const int
|
|
@end smallexample
|
|
@tab @code{ri}
|
|
@item
|
|
@smallexample
|
|
const int*
|
|
@end smallexample
|
|
@tab @code{^ri}
|
|
@item
|
|
@smallexample
|
|
int *const
|
|
@end smallexample
|
|
@tab @code{r^i}
|
|
@end multitable
|
|
|
|
@sp 1
|
|
|
|
@code{const int*} is a pointer to a @code{const int}, and so is
|
|
encoded as @code{^ri}. @code{int* const}, instead, is a @code{const}
|
|
pointer to an @code{int}, and so is encoded as @code{r^i}.
|
|
|
|
Finally, there is a complication when encoding @code{const char *}
|
|
versus @code{char * const}. Because @code{char *} is encoded as
|
|
@code{*} and not as @code{^c}, there is no way to express the fact
|
|
that @code{r} applies to the pointer or to the pointee.
|
|
|
|
Hence, it is assumed as a convention that @code{r*} means @code{const
|
|
char *} (since it is what is most often meant), and there is no way to
|
|
encode @code{char *const}. @code{char *const} would simply be encoded
|
|
as @code{*}, and the @code{const} is lost.
|
|
|
|
@menu
|
|
* Legacy type encoding::
|
|
* @@encode::
|
|
* Method signatures::
|
|
@end menu
|
|
|
|
@node Legacy type encoding
|
|
@subsection Legacy Type Encoding
|
|
|
|
Unfortunately, historically GCC used to have a number of bugs in its
|
|
encoding code. The NeXT runtime expects GCC to emit type encodings in
|
|
this historical format (compatible with GCC-3.3), so when using the
|
|
NeXT runtime, GCC will introduce on purpose a number of incorrect
|
|
encodings:
|
|
|
|
@itemize @bullet
|
|
|
|
@item
|
|
the read-only qualifier of the pointee gets emitted before the '^'.
|
|
The read-only qualifier of the pointer itself gets ignored, unless it
|
|
is a typedef. Also, the 'r' is only emitted for the outermost type.
|
|
|
|
@item
|
|
32-bit longs are encoded as 'l' or 'L', but not always. For typedefs,
|
|
the compiler uses 'i' or 'I' instead if encoding a struct field or a
|
|
pointer.
|
|
|
|
@item
|
|
@code{enum}s are always encoded as 'i' (int) even if they are actually
|
|
unsigned or long.
|
|
|
|
@end itemize
|
|
|
|
In addition to that, the NeXT runtime uses a different encoding for
|
|
bitfields. It encodes them as @code{b} followed by the size, without
|
|
a bit offset or the underlying field type.
|
|
|
|
@node @@encode
|
|
@subsection @code{@@encode}
|
|
|
|
GNU Objective-C supports the @code{@@encode} syntax that allows you to
|
|
create a type encoding from a C/Objective-C type. For example,
|
|
@code{@@encode(int)} is compiled by the compiler into @code{"i"}.
|
|
|
|
@code{@@encode} does not support type qualifiers other than
|
|
@code{const}. For example, @code{@@encode(const char*)} is valid and
|
|
is compiled into @code{"r*"}, while @code{@@encode(bycopy char *)} is
|
|
invalid and will cause a compilation error.
|
|
|
|
@node Method signatures
|
|
@subsection Method Signatures
|
|
|
|
This section documents the encoding of method types, which is rarely
|
|
needed to use Objective-C. You should skip it at a first reading; the
|
|
runtime provides functions that will work on methods and can walk
|
|
through the list of parameters and interpret them for you. These
|
|
functions are part of the public ``API'' and are the preferred way to
|
|
interact with method signatures from user code.
|
|
|
|
But if you need to debug a problem with method signatures and need to
|
|
know how they are implemented (i.e., the ``ABI''), read on.
|
|
|
|
Methods have their ``signature'' encoded and made available to the
|
|
runtime. The ``signature'' encodes all the information required to
|
|
dynamically build invocations of the method at runtime: return type
|
|
and arguments.
|
|
|
|
The ``signature'' is a null-terminated string, composed of the following:
|
|
|
|
@itemize @bullet
|
|
|
|
@item
|
|
The return type, including type qualifiers. For example, a method
|
|
returning @code{int} would have @code{i} here.
|
|
|
|
@item
|
|
The total size (in bytes) required to pass all the parameters. This
|
|
includes the two hidden parameters (the object @code{self} and the
|
|
method selector @code{_cmd}).
|
|
|
|
@item
|
|
Each argument, with the type encoding, followed by the offset (in
|
|
bytes) of the argument in the list of parameters.
|
|
|
|
@end itemize
|
|
|
|
For example, a method with no arguments and returning @code{int} would
|
|
have the signature @code{i8@@0:4} if the size of a pointer is 4. The
|
|
signature is interpreted as follows: the @code{i} is the return type
|
|
(an @code{int}), the @code{8} is the total size of the parameters in
|
|
bytes (two pointers each of size 4), the @code{@@0} is the first
|
|
parameter (an object at byte offset @code{0}) and @code{:4} is the
|
|
second parameter (a @code{SEL} at byte offset @code{4}).
|
|
|
|
You can easily find more examples by running the ``strings'' program
|
|
on an Objective-C object file compiled by GCC. You'll see a lot of
|
|
strings that look very much like @code{i8@@0:4}. They are signatures
|
|
of Objective-C methods.
|
|
|
|
|
|
@node Garbage Collection
|
|
@section Garbage Collection
|
|
|
|
This section is specific for the GNU Objective-C runtime. If you are
|
|
using a different runtime, you can skip it.
|
|
|
|
Support for garbage collection with the GNU runtime has been added by
|
|
using a powerful conservative garbage collector, known as the
|
|
Boehm-Demers-Weiser conservative garbage collector.
|
|
|
|
To enable the support for it you have to configure the compiler using
|
|
an additional argument, @w{@option{--enable-objc-gc}}. This will
|
|
build the boehm-gc library, and build an additional runtime library
|
|
which has several enhancements to support the garbage collector. The
|
|
new library has a new name, @file{libobjc_gc.a} to not conflict with
|
|
the non-garbage-collected library.
|
|
|
|
When the garbage collector is used, the objects are allocated using the
|
|
so-called typed memory allocation mechanism available in the
|
|
Boehm-Demers-Weiser collector. This mode requires precise information on
|
|
where pointers are located inside objects. This information is computed
|
|
once per class, immediately after the class has been initialized.
|
|
|
|
There is a new runtime function @code{class_ivar_set_gcinvisible()}
|
|
which can be used to declare a so-called @dfn{weak pointer}
|
|
reference. Such a pointer is basically hidden for the garbage collector;
|
|
this can be useful in certain situations, especially when you want to
|
|
keep track of the allocated objects, yet allow them to be
|
|
collected. This kind of pointers can only be members of objects, you
|
|
cannot declare a global pointer as a weak reference. Every type which is
|
|
a pointer type can be declared a weak pointer, including @code{id},
|
|
@code{Class} and @code{SEL}.
|
|
|
|
Here is an example of how to use this feature. Suppose you want to
|
|
implement a class whose instances hold a weak pointer reference; the
|
|
following class does this:
|
|
|
|
@smallexample
|
|
|
|
@@interface WeakPointer : Object
|
|
@{
|
|
const void* weakPointer;
|
|
@}
|
|
|
|
- initWithPointer:(const void*)p;
|
|
- (const void*)weakPointer;
|
|
@@end
|
|
|
|
|
|
@@implementation WeakPointer
|
|
|
|
+ (void)initialize
|
|
@{
|
|
if (self == objc_lookUpClass ("WeakPointer"))
|
|
class_ivar_set_gcinvisible (self, "weakPointer", YES);
|
|
@}
|
|
|
|
- initWithPointer:(const void*)p
|
|
@{
|
|
weakPointer = p;
|
|
return self;
|
|
@}
|
|
|
|
- (const void*)weakPointer
|
|
@{
|
|
return weakPointer;
|
|
@}
|
|
|
|
@@end
|
|
|
|
@end smallexample
|
|
|
|
Weak pointers are supported through a new type character specifier
|
|
represented by the @samp{!} character. The
|
|
@code{class_ivar_set_gcinvisible()} function adds or removes this
|
|
specifier to the string type description of the instance variable named
|
|
as argument.
|
|
|
|
@c =========================================================================
|
|
@node Constant string objects
|
|
@section Constant String Objects
|
|
|
|
GNU Objective-C provides constant string objects that are generated
|
|
directly by the compiler. You declare a constant string object by
|
|
prefixing a C constant string with the character @samp{@@}:
|
|
|
|
@smallexample
|
|
id myString = @@"this is a constant string object";
|
|
@end smallexample
|
|
|
|
The constant string objects are by default instances of the
|
|
@code{NXConstantString} class which is provided by the GNU Objective-C
|
|
runtime. To get the definition of this class you must include the
|
|
@file{objc/NXConstStr.h} header file.
|
|
|
|
User defined libraries may want to implement their own constant string
|
|
class. To be able to support them, the GNU Objective-C compiler provides
|
|
a new command line options @option{-fconstant-string-class=@var{class-name}}.
|
|
The provided class should adhere to a strict structure, the same
|
|
as @code{NXConstantString}'s structure:
|
|
|
|
@smallexample
|
|
|
|
@@interface MyConstantStringClass
|
|
@{
|
|
Class isa;
|
|
char *c_string;
|
|
unsigned int len;
|
|
@}
|
|
@@end
|
|
|
|
@end smallexample
|
|
|
|
@code{NXConstantString} inherits from @code{Object}; user class
|
|
libraries may choose to inherit the customized constant string class
|
|
from a different class than @code{Object}. There is no requirement in
|
|
the methods the constant string class has to implement, but the final
|
|
ivar layout of the class must be the compatible with the given
|
|
structure.
|
|
|
|
When the compiler creates the statically allocated constant string
|
|
object, the @code{c_string} field will be filled by the compiler with
|
|
the string; the @code{length} field will be filled by the compiler with
|
|
the string length; the @code{isa} pointer will be filled with
|
|
@code{NULL} by the compiler, and it will later be fixed up automatically
|
|
at runtime by the GNU Objective-C runtime library to point to the class
|
|
which was set by the @option{-fconstant-string-class} option when the
|
|
object file is loaded (if you wonder how it works behind the scenes, the
|
|
name of the class to use, and the list of static objects to fixup, are
|
|
stored by the compiler in the object file in a place where the GNU
|
|
runtime library will find them at runtime).
|
|
|
|
As a result, when a file is compiled with the
|
|
@option{-fconstant-string-class} option, all the constant string objects
|
|
will be instances of the class specified as argument to this option. It
|
|
is possible to have multiple compilation units referring to different
|
|
constant string classes, neither the compiler nor the linker impose any
|
|
restrictions in doing this.
|
|
|
|
@c =========================================================================
|
|
@node compatibility_alias
|
|
@section @code{compatibility_alias}
|
|
|
|
The keyword @code{@@compatibility_alias} allows you to define a class name
|
|
as equivalent to another class name. For example:
|
|
|
|
@smallexample
|
|
@@compatibility_alias WOApplication GSWApplication;
|
|
@end smallexample
|
|
|
|
tells the compiler that each time it encounters @code{WOApplication} as
|
|
a class name, it should replace it with @code{GSWApplication} (that is,
|
|
@code{WOApplication} is just an alias for @code{GSWApplication}).
|
|
|
|
There are some constraints on how this can be used---
|
|
|
|
@itemize @bullet
|
|
|
|
@item @code{WOApplication} (the alias) must not be an existing class;
|
|
|
|
@item @code{GSWApplication} (the real class) must be an existing class.
|
|
|
|
@end itemize
|
|
|
|
@c =========================================================================
|
|
@node Exceptions
|
|
@section Exceptions
|
|
|
|
GNU Objective-C provides exception support built into the language, as
|
|
in the following example:
|
|
|
|
@smallexample
|
|
@@try @{
|
|
@dots{}
|
|
@@throw expr;
|
|
@dots{}
|
|
@}
|
|
@@catch (AnObjCClass *exc) @{
|
|
@dots{}
|
|
@@throw expr;
|
|
@dots{}
|
|
@@throw;
|
|
@dots{}
|
|
@}
|
|
@@catch (AnotherClass *exc) @{
|
|
@dots{}
|
|
@}
|
|
@@catch (id allOthers) @{
|
|
@dots{}
|
|
@}
|
|
@@finally @{
|
|
@dots{}
|
|
@@throw expr;
|
|
@dots{}
|
|
@}
|
|
@end smallexample
|
|
|
|
The @code{@@throw} statement may appear anywhere in an Objective-C or
|
|
Objective-C++ program; when used inside of a @code{@@catch} block, the
|
|
@code{@@throw} may appear without an argument (as shown above), in
|
|
which case the object caught by the @code{@@catch} will be rethrown.
|
|
|
|
Note that only (pointers to) Objective-C objects may be thrown and
|
|
caught using this scheme. When an object is thrown, it will be caught
|
|
by the nearest @code{@@catch} clause capable of handling objects of
|
|
that type, analogously to how @code{catch} blocks work in C++ and
|
|
Java. A @code{@@catch(id @dots{})} clause (as shown above) may also
|
|
be provided to catch any and all Objective-C exceptions not caught by
|
|
previous @code{@@catch} clauses (if any).
|
|
|
|
The @code{@@finally} clause, if present, will be executed upon exit
|
|
from the immediately preceding @code{@@try @dots{} @@catch} section.
|
|
This will happen regardless of whether any exceptions are thrown,
|
|
caught or rethrown inside the @code{@@try @dots{} @@catch} section,
|
|
analogously to the behavior of the @code{finally} clause in Java.
|
|
|
|
There are several caveats to using the new exception mechanism:
|
|
|
|
@itemize @bullet
|
|
@item
|
|
The @option{-fobjc-exceptions} command line option must be used when
|
|
compiling Objective-C files that use exceptions.
|
|
|
|
@item
|
|
With the GNU runtime, exceptions are always implemented as ``native''
|
|
exceptions and it is recommended that the @option{-fexceptions} and
|
|
@option{-shared-libgcc} options are used when linking.
|
|
|
|
@item
|
|
With the NeXT runtime, although currently designed to be binary
|
|
compatible with @code{NS_HANDLER}-style idioms provided by the
|
|
@code{NSException} class, the new exceptions can only be used on Mac
|
|
OS X 10.3 (Panther) and later systems, due to additional functionality
|
|
needed in the NeXT Objective-C runtime.
|
|
|
|
@item
|
|
As mentioned above, the new exceptions do not support handling
|
|
types other than Objective-C objects. Furthermore, when used from
|
|
Objective-C++, the Objective-C exception model does not interoperate with C++
|
|
exceptions at this time. This means you cannot @code{@@throw} an exception
|
|
from Objective-C and @code{catch} it in C++, or vice versa
|
|
(i.e., @code{throw @dots{} @@catch}).
|
|
@end itemize
|
|
|
|
@c =========================================================================
|
|
@node Synchronization
|
|
@section Synchronization
|
|
|
|
GNU Objective-C provides support for synchronized blocks:
|
|
|
|
@smallexample
|
|
@@synchronized (ObjCClass *guard) @{
|
|
@dots{}
|
|
@}
|
|
@end smallexample
|
|
|
|
Upon entering the @code{@@synchronized} block, a thread of execution
|
|
shall first check whether a lock has been placed on the corresponding
|
|
@code{guard} object by another thread. If it has, the current thread
|
|
shall wait until the other thread relinquishes its lock. Once
|
|
@code{guard} becomes available, the current thread will place its own
|
|
lock on it, execute the code contained in the @code{@@synchronized}
|
|
block, and finally relinquish the lock (thereby making @code{guard}
|
|
available to other threads).
|
|
|
|
Unlike Java, Objective-C does not allow for entire methods to be
|
|
marked @code{@@synchronized}. Note that throwing exceptions out of
|
|
@code{@@synchronized} blocks is allowed, and will cause the guarding
|
|
object to be unlocked properly.
|
|
|
|
Because of the interactions between synchronization and exception
|
|
handling, you can only use @code{@@synchronized} when compiling with
|
|
exceptions enabled, that is with the command line option
|
|
@option{-fobjc-exceptions}.
|
|
|
|
|
|
@c =========================================================================
|
|
@node Fast enumeration
|
|
@section Fast Enumeration
|
|
|
|
@menu
|
|
* Using fast enumeration::
|
|
* c99-like fast enumeration syntax::
|
|
* Fast enumeration details::
|
|
* Fast enumeration protocol::
|
|
@end menu
|
|
|
|
@c ================================
|
|
@node Using fast enumeration
|
|
@subsection Using Fast Enumeration
|
|
|
|
GNU Objective-C provides support for the fast enumeration syntax:
|
|
|
|
@smallexample
|
|
id array = @dots{};
|
|
id object;
|
|
|
|
for (object in array)
|
|
@{
|
|
/* Do something with 'object' */
|
|
@}
|
|
@end smallexample
|
|
|
|
@code{array} needs to be an Objective-C object (usually a collection
|
|
object, for example an array, a dictionary or a set) which implements
|
|
the ``Fast Enumeration Protocol'' (see below). If you are using a
|
|
Foundation library such as GNUstep Base or Apple Cocoa Foundation, all
|
|
collection objects in the library implement this protocol and can be
|
|
used in this way.
|
|
|
|
The code above would iterate over all objects in @code{array}. For
|
|
each of them, it assigns it to @code{object}, then executes the
|
|
@code{Do something with 'object'} statements.
|
|
|
|
Here is a fully worked-out example using a Foundation library (which
|
|
provides the implementation of @code{NSArray}, @code{NSString} and
|
|
@code{NSLog}):
|
|
|
|
@smallexample
|
|
NSArray *array = [NSArray arrayWithObjects: @@"1", @@"2", @@"3", nil];
|
|
NSString *object;
|
|
|
|
for (object in array)
|
|
NSLog (@@"Iterating over %@@", object);
|
|
@end smallexample
|
|
|
|
|
|
@c ================================
|
|
@node c99-like fast enumeration syntax
|
|
@subsection C99-Like Fast Enumeration Syntax
|
|
|
|
A c99-like declaration syntax is also allowed:
|
|
|
|
@smallexample
|
|
id array = @dots{};
|
|
|
|
for (id object in array)
|
|
@{
|
|
/* Do something with 'object' */
|
|
@}
|
|
@end smallexample
|
|
|
|
this is completely equivalent to:
|
|
|
|
@smallexample
|
|
id array = @dots{};
|
|
|
|
@{
|
|
id object;
|
|
for (object in array)
|
|
@{
|
|
/* Do something with 'object' */
|
|
@}
|
|
@}
|
|
@end smallexample
|
|
|
|
but can save some typing.
|
|
|
|
Note that the option @option{-std=c99} is not required to allow this
|
|
syntax in Objective-C.
|
|
|
|
@c ================================
|
|
@node Fast enumeration details
|
|
@subsection Fast Enumeration Details
|
|
|
|
Here is a more technical description with the gory details. Consider the code
|
|
|
|
@smallexample
|
|
for (@var{object expression} in @var{collection expression})
|
|
@{
|
|
@var{statements}
|
|
@}
|
|
@end smallexample
|
|
|
|
here is what happens when you run it:
|
|
|
|
@itemize @bullet
|
|
@item
|
|
@code{@var{collection expression}} is evaluated exactly once and the
|
|
result is used as the collection object to iterate over. This means
|
|
it is safe to write code such as @code{for (object in [NSDictionary
|
|
keyEnumerator]) @dots{}}.
|
|
|
|
@item
|
|
the iteration is implemented by the compiler by repeatedly getting
|
|
batches of objects from the collection object using the fast
|
|
enumeration protocol (see below), then iterating over all objects in
|
|
the batch. This is faster than a normal enumeration where objects are
|
|
retrieved one by one (hence the name ``fast enumeration'').
|
|
|
|
@item
|
|
if there are no objects in the collection, then
|
|
@code{@var{object expression}} is set to @code{nil} and the loop
|
|
immediately terminates.
|
|
|
|
@item
|
|
if there are objects in the collection, then for each object in the
|
|
collection (in the order they are returned) @code{@var{object expression}}
|
|
is set to the object, then @code{@var{statements}} are executed.
|
|
|
|
@item
|
|
@code{@var{statements}} can contain @code{break} and @code{continue}
|
|
commands, which will abort the iteration or skip to the next loop
|
|
iteration as expected.
|
|
|
|
@item
|
|
when the iteration ends because there are no more objects to iterate
|
|
over, @code{@var{object expression}} is set to @code{nil}. This allows
|
|
you to determine whether the iteration finished because a @code{break}
|
|
command was used (in which case @code{@var{object expression}} will remain
|
|
set to the last object that was iterated over) or because it iterated
|
|
over all the objects (in which case @code{@var{object expression}} will be
|
|
set to @code{nil}).
|
|
|
|
@item
|
|
@code{@var{statements}} must not make any changes to the collection
|
|
object; if they do, it is a hard error and the fast enumeration
|
|
terminates by invoking @code{objc_enumerationMutation}, a runtime
|
|
function that normally aborts the program but which can be customized
|
|
by Foundation libraries via @code{objc_set_mutation_handler} to do
|
|
something different, such as raising an exception.
|
|
|
|
@end itemize
|
|
|
|
@c ================================
|
|
@node Fast enumeration protocol
|
|
@subsection Fast Enumeration Protocol
|
|
|
|
If you want your own collection object to be usable with fast
|
|
enumeration, you need to have it implement the method
|
|
|
|
@smallexample
|
|
- (unsigned long) countByEnumeratingWithState: (NSFastEnumerationState *)state
|
|
objects: (id *)objects
|
|
count: (unsigned long)len;
|
|
@end smallexample
|
|
|
|
where @code{NSFastEnumerationState} must be defined in your code as follows:
|
|
|
|
@smallexample
|
|
typedef struct
|
|
@{
|
|
unsigned long state;
|
|
id *itemsPtr;
|
|
unsigned long *mutationsPtr;
|
|
unsigned long extra[5];
|
|
@} NSFastEnumerationState;
|
|
@end smallexample
|
|
|
|
If no @code{NSFastEnumerationState} is defined in your code, the
|
|
compiler will automatically replace @code{NSFastEnumerationState *}
|
|
with @code{struct __objcFastEnumerationState *}, where that type is
|
|
silently defined by the compiler in an identical way. This can be
|
|
confusing and we recommend that you define
|
|
@code{NSFastEnumerationState} (as shown above) instead.
|
|
|
|
The method is called repeatedly during a fast enumeration to retrieve
|
|
batches of objects. Each invocation of the method should retrieve the
|
|
next batch of objects.
|
|
|
|
The return value of the method is the number of objects in the current
|
|
batch; this should not exceed @code{len}, which is the maximum size of
|
|
a batch as requested by the caller. The batch itself is returned in
|
|
the @code{itemsPtr} field of the @code{NSFastEnumerationState} struct.
|
|
|
|
To help with returning the objects, the @code{objects} array is a C
|
|
array preallocated by the caller (on the stack) of size @code{len}.
|
|
In many cases you can put the objects you want to return in that
|
|
@code{objects} array, then do @code{itemsPtr = objects}. But you
|
|
don't have to; if your collection already has the objects to return in
|
|
some form of C array, it could return them from there instead.
|
|
|
|
The @code{state} and @code{extra} fields of the
|
|
@code{NSFastEnumerationState} structure allows your collection object
|
|
to keep track of the state of the enumeration. In a simple array
|
|
implementation, @code{state} may keep track of the index of the last
|
|
object that was returned, and @code{extra} may be unused.
|
|
|
|
The @code{mutationsPtr} field of the @code{NSFastEnumerationState} is
|
|
used to keep track of mutations. It should point to a number; before
|
|
working on each object, the fast enumeration loop will check that this
|
|
number has not changed. If it has, a mutation has happened and the
|
|
fast enumeration will abort. So, @code{mutationsPtr} could be set to
|
|
point to some sort of version number of your collection, which is
|
|
increased by one every time there is a change (for example when an
|
|
object is added or removed). Or, if you are content with less strict
|
|
mutation checks, it could point to the number of objects in your
|
|
collection or some other value that can be checked to perform an
|
|
approximate check that the collection has not been mutated.
|
|
|
|
Finally, note how we declared the @code{len} argument and the return
|
|
value to be of type @code{unsigned long}. They could also be declared
|
|
to be of type @code{unsigned int} and everything would still work.
|
|
|
|
@c =========================================================================
|
|
@node Messaging with the GNU Objective-C runtime
|
|
@section Messaging with the GNU Objective-C Runtime
|
|
|
|
This section is specific for the GNU Objective-C runtime. If you are
|
|
using a different runtime, you can skip it.
|
|
|
|
The implementation of messaging in the GNU Objective-C runtime is
|
|
designed to be portable, and so is based on standard C.
|
|
|
|
Sending a message in the GNU Objective-C runtime is composed of two
|
|
separate steps. First, there is a call to the lookup function,
|
|
@code{objc_msg_lookup ()} (or, in the case of messages to super,
|
|
@code{objc_msg_lookup_super ()}). This runtime function takes as
|
|
argument the receiver and the selector of the method to be called; it
|
|
returns the @code{IMP}, that is a pointer to the function implementing
|
|
the method. The second step of method invocation consists of casting
|
|
this pointer function to the appropriate function pointer type, and
|
|
calling the function pointed to it with the right arguments.
|
|
|
|
For example, when the compiler encounters a method invocation such as
|
|
@code{[object init]}, it compiles it into a call to
|
|
@code{objc_msg_lookup (object, @@selector(init))} followed by a cast
|
|
of the returned value to the appropriate function pointer type, and
|
|
then it calls it.
|
|
|
|
@menu
|
|
* Dynamically registering methods::
|
|
* Forwarding hook::
|
|
@end menu
|
|
|
|
@c =========================================================================
|
|
@node Dynamically registering methods
|
|
@subsection Dynamically Registering Methods
|
|
|
|
If @code{objc_msg_lookup()} does not find a suitable method
|
|
implementation, because the receiver does not implement the required
|
|
method, it tries to see if the class can dynamically register the
|
|
method.
|
|
|
|
To do so, the runtime checks if the class of the receiver implements
|
|
the method
|
|
|
|
@smallexample
|
|
+ (BOOL) resolveInstanceMethod: (SEL)selector;
|
|
@end smallexample
|
|
|
|
in the case of an instance method, or
|
|
|
|
@smallexample
|
|
+ (BOOL) resolveClassMethod: (SEL)selector;
|
|
@end smallexample
|
|
|
|
in the case of a class method. If the class implements it, the
|
|
runtime invokes it, passing as argument the selector of the original
|
|
method, and if it returns @code{YES}, the runtime tries the lookup
|
|
again, which could now succeed if a matching method was added
|
|
dynamically by @code{+resolveInstanceMethod:} or
|
|
@code{+resolveClassMethod:}.
|
|
|
|
This allows classes to dynamically register methods (by adding them to
|
|
the class using @code{class_addMethod}) when they are first called.
|
|
To do so, a class should implement @code{+resolveInstanceMethod:} (or,
|
|
depending on the case, @code{+resolveClassMethod:}) and have it
|
|
recognize the selectors of methods that can be registered dynamically
|
|
at runtime, register them, and return @code{YES}. It should return
|
|
@code{NO} for methods that it does not dynamically registered at
|
|
runtime.
|
|
|
|
If @code{+resolveInstanceMethod:} (or @code{+resolveClassMethod:}) is
|
|
not implemented or returns @code{NO}, the runtime then tries the
|
|
forwarding hook.
|
|
|
|
Support for @code{+resolveInstanceMethod:} and
|
|
@code{resolveClassMethod:} was added to the GNU Objective-C runtime in
|
|
GCC version 4.6.
|
|
|
|
@c =========================================================================
|
|
@node Forwarding hook
|
|
@subsection Forwarding Hook
|
|
|
|
The GNU Objective-C runtime provides a hook, called
|
|
@code{__objc_msg_forward2}, which is called by
|
|
@code{objc_msg_lookup()} when it cannot find a method implementation in
|
|
the runtime tables and after calling @code{+resolveInstanceMethod:}
|
|
and @code{+resolveClassMethod:} has been attempted and did not succeed
|
|
in dynamically registering the method.
|
|
|
|
To configure the hook, you set the global variable
|
|
@code{__objc_msg_forward2} to a function with the same argument and
|
|
return types of @code{objc_msg_lookup()}. When
|
|
@code{objc_msg_lookup()} cannot find a method implementation, it
|
|
invokes the hook function you provided to get a method implementation
|
|
to return. So, in practice @code{__objc_msg_forward2} allows you to
|
|
extend @code{objc_msg_lookup()} by adding some custom code that is
|
|
called to do a further lookup when no standard method implementation
|
|
can be found using the normal lookup.
|
|
|
|
This hook is generally reserved for ``Foundation'' libraries such as
|
|
GNUstep Base, which use it to implement their high-level method
|
|
forwarding API, typically based around the @code{forwardInvocation:}
|
|
method. So, unless you are implementing your own ``Foundation''
|
|
library, you should not set this hook.
|
|
|
|
In a typical forwarding implementation, the @code{__objc_msg_forward2}
|
|
hook function determines the argument and return type of the method
|
|
that is being looked up, and then creates a function that takes these
|
|
arguments and has that return type, and returns it to the caller.
|
|
Creating this function is non-trivial and is typically performed using
|
|
a dedicated library such as @code{libffi}.
|
|
|
|
The forwarding method implementation thus created is returned by
|
|
@code{objc_msg_lookup()} and is executed as if it was a normal method
|
|
implementation. When the forwarding method implementation is called,
|
|
it is usually expected to pack all arguments into some sort of object
|
|
(typically, an @code{NSInvocation} in a ``Foundation'' library), and
|
|
hand it over to the programmer (@code{forwardInvocation:}) who is then
|
|
allowed to manipulate the method invocation using a high-level API
|
|
provided by the ``Foundation'' library. For example, the programmer
|
|
may want to examine the method invocation arguments and name and
|
|
potentially change them before forwarding the method invocation to one
|
|
or more local objects (@code{performInvocation:}) or even to remote
|
|
objects (by using Distributed Objects or some other mechanism). When
|
|
all this completes, the return value is passed back and must be
|
|
returned correctly to the original caller.
|
|
|
|
Note that the GNU Objective-C runtime currently provides no support
|
|
for method forwarding or method invocations other than the
|
|
@code{__objc_msg_forward2} hook.
|
|
|
|
If the forwarding hook does not exist or returns @code{NULL}, the
|
|
runtime currently attempts forwarding using an older, deprecated API,
|
|
and if that fails, it aborts the program. In future versions of the
|
|
GNU Objective-C runtime, the runtime will immediately abort.
|