]>
Commit | Line | Data |
---|---|---|
c63539ff ML |
1 | .. |
2 | Copyright 1988-2022 Free Software Foundation, Inc. | |
3 | This is part of the GCC manual. | |
4 | For copying conditions, see the copyright.rst file. | |
5 | ||
6 | .. _executing-code-before-main: | |
7 | ||
8 | +load: Executing Code before main | |
9 | ********************************* | |
10 | ||
11 | This section is specific for the GNU Objective-C runtime. If you are | |
12 | using a different runtime, you can skip it. | |
13 | ||
14 | The GNU Objective-C runtime provides a way that allows you to execute | |
15 | code before the execution of the program enters the ``main`` | |
16 | function. The code is executed on a per-class and a per-category basis, | |
17 | through a special class method ``+load``. | |
18 | ||
19 | This facility is very useful if you want to initialize global variables | |
20 | which can be accessed by the program directly, without sending a message | |
21 | to the class first. The usual way to initialize global variables, in the | |
22 | ``+initialize`` method, might not be useful because | |
23 | ``+initialize`` is only called when the first message is sent to a | |
24 | class object, which in some cases could be too late. | |
25 | ||
26 | Suppose for example you have a ``FileStream`` class that declares | |
27 | ``Stdin``, ``Stdout`` and ``Stderr`` as global variables, like | |
28 | below: | |
29 | ||
30 | .. code-block:: objective-c | |
31 | ||
32 | FileStream *Stdin = nil; | |
33 | FileStream *Stdout = nil; | |
34 | FileStream *Stderr = nil; | |
35 | ||
36 | @implementation FileStream | |
37 | ||
38 | + (void)initialize | |
39 | { | |
40 | Stdin = [[FileStream new] initWithFd:0]; | |
41 | Stdout = [[FileStream new] initWithFd:1]; | |
42 | Stderr = [[FileStream new] initWithFd:2]; | |
43 | } | |
44 | ||
45 | /* Other methods here */ | |
46 | @end | |
47 | ||
48 | In this example, the initialization of ``Stdin``, ``Stdout`` and | |
49 | ``Stderr`` in ``+initialize`` occurs too late. The programmer can | |
50 | send a message to one of these objects before the variables are actually | |
51 | initialized, thus sending messages to the ``nil`` object. The | |
52 | ``+initialize`` method which actually initializes the global | |
53 | variables is not invoked until the first message is sent to the class | |
54 | object. The solution would require these variables to be initialized | |
55 | just before entering ``main``. | |
56 | ||
57 | The correct solution of the above problem is to use the ``+load`` | |
58 | method instead of ``+initialize`` : | |
59 | ||
60 | .. code-block:: objective-c | |
61 | ||
62 | @implementation FileStream | |
63 | ||
64 | + (void)load | |
65 | { | |
66 | Stdin = [[FileStream new] initWithFd:0]; | |
67 | Stdout = [[FileStream new] initWithFd:1]; | |
68 | Stderr = [[FileStream new] initWithFd:2]; | |
69 | } | |
70 | ||
71 | /* Other methods here */ | |
72 | @end | |
73 | ||
74 | The ``+load`` is a method that is not overridden by categories. If a | |
75 | class and a category of it both implement ``+load``, both methods are | |
76 | invoked. This allows some additional initializations to be performed in | |
77 | a category. | |
78 | ||
79 | This mechanism is not intended to be a replacement for ``+initialize``. | |
80 | You should be aware of its limitations when you decide to use it | |
81 | instead of ``+initialize``. | |
82 | ||
83 | .. toctree:: | |
84 | :maxdepth: 2 | |
85 | ||
86 | ||
87 | .. _what-you-can-and-what-you-cannot-do-in-+load: | |
88 | ||
89 | What You Can and Cannot Do in +load | |
90 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
91 | ||
92 | ``+load`` is to be used only as a last resort. Because it is | |
93 | executed very early, most of the Objective-C runtime machinery will | |
94 | not be ready when ``+load`` is executed; hence ``+load`` works | |
95 | best for executing C code that is independent on the Objective-C | |
96 | runtime. | |
97 | ||
98 | The ``+load`` implementation in the GNU runtime guarantees you the | |
99 | following things: | |
100 | ||
101 | * you can write whatever C code you like; | |
102 | ||
103 | * you can allocate and send messages to objects whose class is implemented | |
104 | in the same file; | |
105 | ||
106 | * the ``+load`` implementation of all super classes of a class are | |
107 | executed before the ``+load`` of that class is executed; | |
108 | ||
109 | * the ``+load`` implementation of a class is executed before the | |
110 | ``+load`` implementation of any category. | |
111 | ||
112 | In particular, the following things, even if they can work in a | |
113 | particular case, are not guaranteed: | |
114 | ||
115 | * allocation of or sending messages to arbitrary objects; | |
116 | ||
117 | * allocation of or sending messages to objects whose classes have a | |
118 | category implemented in the same file; | |
119 | ||
120 | * sending messages to Objective-C constant strings (``@"this is a | |
121 | constant string"``); | |
122 | ||
123 | You should make no assumptions about receiving ``+load`` in sibling | |
124 | classes when you write ``+load`` of a class. The order in which | |
125 | sibling classes receive ``+load`` is not guaranteed. | |
126 | ||
127 | The order in which ``+load`` and ``+initialize`` are called could | |
128 | be problematic if this matters. If you don't allocate objects inside | |
129 | ``+load``, it is guaranteed that ``+load`` is called before | |
130 | ``+initialize``. If you create an object inside ``+load`` the | |
131 | ``+initialize`` method of object's class is invoked even if | |
132 | ``+load`` was not invoked. Note if you explicitly call ``+load`` | |
133 | on a class, ``+initialize`` will be called first. To avoid possible | |
134 | problems try to implement only one of these methods. | |
135 | ||
136 | The ``+load`` method is also invoked when a bundle is dynamically | |
137 | loaded into your running program. This happens automatically without any | |
138 | intervening operation from you. When you write bundles and you need to | |
139 | write ``+load`` you can safely create and send messages to objects whose | |
140 | classes already exist in the running program. The same restrictions as | |
3ed1b4ce | 141 | above apply to classes defined in bundle. |