1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
|
{
objcrtl.pas
Copyright (C) 2009 Dmitry Boyarintsev
This unit is a pascal binding for dynamic Objective-C Run-time Library
headers included with XCode 3.1.2
The original copyright note of is kept on each include file
}
unit objcrtl;
{$mode objfpc}{$H+}
interface
uses
dynlibs;
const
DefaultObjCLibName : AnsiString = 'libobjc.A.dylib';
{ Overview
--------
This document describes the Mac OS X Objective-C 2.0 runtime library support
functions and data structures. The functions are implemented in the shared
library found at /usr/lib/libobjc.A.dylib. This shared library provides support
for the dynamic properties of the Objective-C language, and as such is linked
to by all Objective-C applications.
This reference is useful primarily for developing bridge layers between
Objective-C and other languages, or for low-level debugging. You typically do
not need to use the Objective-C runtime library directly when programming
in Objective-C.
The Mac OS X implementation of the Objective-C runtime library is unique
to the Mac OS X platform. For other platforms, the GNU Compiler Collection
provides a different implementation with a similar API. This document covers
only the Mac OS X implementation.
The low-level Objective-C runtime API is significantly updated in Mac OS X
version 10.5. Many functions and all existing data structures are replaced
with new functions. The old functions and structures are deprecated in 32-bit
and absent in 64-bit mode. The API constrains several values to 32-bit ints
even in 64-bit mode—class count, protocol count, methods per class, ivars
per class, arguments per method, sizeof(all arguments) per method, and
class version number. In addition, the new Objective-C ABI (not described here)
further constrains sizeof(anInstance) to 32 bits, and three other values
to 24 bits—methods per class, ivars per class, and sizeof(a single ivar).
Finally, the obsolete NXHashTable and NXMapTable are limited to 4 billion items.
“Deprecated” below means “deprecated in Mac OS X version 10.5 for 32-bit code,
and disallowed for 64-bit code.
Legacy and Modern Versions
--------------------------
There are two versions of the Objective-C runtime—“modern” and “legacy”.
The modern version was introduced with Objective-C 2.0 and includes a number
of new features. The programming interface for the legacy version of the runtime
is described in Objective-C 1 Runtime Reference; the programming interface
for the modern version of the runtime is described in Objective-C 2.0 Runtime
Reference.
The most notable new feature is that instance variables in the modern runtime are “non-fragile”:
* In the legacy runtime, if you change the layout of instance variables in a class,
you must recompile classes that inherit from it.
* In the modern runtime, if you change the layout of instance variables in a class,
you do not have to recompile classes that inherit from it.
In addition, the modern runtime supports instance variable synthesis
for declared properties (see Declared Properties in The Objective-C 2.0 Programming Language).
Platforms
---------
iPhone applications and 64-bit programs on Mac OS X v10.5 and later use
the modern version of the runtime.
Other programs (32-bit programs on Mac OS X desktop) use the legacy version
of the runtime.
}
type
//todo: types MUST BE declared properly as 2.0 opaques
SEL = Pointer;
IMP = Pointer;
id = Pointer; //??
size_t = LongWord;
_Class = Pointer;
Ivar = Pointer;
PProtocol = Pointer;
PArrayPProtocol = Pointer;
BOOL = Boolean;
PIvar = Pointer;
Method = Pointer;
PMethod = Pointer;
Protocol = Pointer;
objc_property_t = Pointer;
Pobjc_property_t = Pointer;
uint8_t = byte;
Pobjc_method_description = Pointer;
ptrdiff_t = Pointer;
objc_method_description = Pointer;
TMutationHandlerProc = Pointer;
pobjc_super = ^objc_super;
objc_super = packed record
reciever : id;
class_ : _class;
end;
var
sel_getName : function (sel: SEL): PChar; cdecl = nil;
sel_registerName : function (str: PChar): SEL; cdecl = nil;
object_getClassName : function (obj: id): PChar; cdecl = nil;
object_getIndexedIvars : function (obj: id ): Pointer; cdecl = nil;
sel_isMapped: function (sel: SEL): Boolean; cdecl = nil;
sel_getUid: function (const str: PChar): SEL; cdecl = nil;
object_copy : function (obj:id; size:size_t):id; cdecl = nil;
object_dispose : function (obj:id):id; cdecl = nil;
object_getClass : function (obj:id): _Class; cdecl = nil;
object_setClass : function (obj:id; cls: _Class):_Class; cdecl = nil;
object_getIvar : function (obj:id; ivar:Ivar):id; cdecl = nil;
object_setIvar : procedure (obj:id; ivar:Ivar; value:id); cdecl = nil;
object_setInstanceVariable : function (obj:id; name:pchar; value:pointer):Ivar; cdecl = nil;
object_getInstanceVariable : function (obj:id; name:pchar; var outValue: Pointer):Ivar; cdecl = nil;
objc_getClass : function (name:pchar):id; cdecl = nil;
objc_getMetaClass : function (name:pchar):id; cdecl = nil;
objc_lookUpClass : function (name:pchar):id; cdecl = nil;
objc_getRequiredClass : function (name:pchar):id; cdecl = nil;
objc_getFutureClass : function (name:pchar):_Class; cdecl = nil;
objc_setFutureClass : procedure (cls:_Class; name:pchar); cdecl = nil;
objc_getClassList : function (buffer:pClass; bufferCount:longint):longint; cdecl = nil;
objc_getProtocol : function (name:pchar): PProtocol; cdecl = nil;
objc_copyProtocolList : function (outCount:pdword):PArrayPProtocol; cdecl = nil;
class_getName : function (cls:_Class):PChar; cdecl = nil;
class_isMetaClass : function (cls:_Class):BOOL; cdecl = nil;
class_getSuperclass : function (cls:_Class):_Class; cdecl = nil;
class_setSuperclass : function (cls: _Class; newSuper: _Class): _Class; cdecl = nil;
class_getVersion : function (cls:_Class):longint; cdecl = nil;
class_setVersion : procedure (cls:_Class; version:longint); cdecl = nil;
class_getInstanceSize : function (cls:_Class):size_t; cdecl = nil;
class_getInstanceVariable : function (cls:_Class; name:pchar):Ivar; cdecl = nil;
class_getClassVariable : function (cls:_Class; name:pchar):Ivar; cdecl = nil;
class_copyIvarList : function (cls:_Class; outCount:pdword):PIvar; cdecl = nil;
class_getInstanceMethod : function (cls:_Class; name:SEL):Method; cdecl = nil;
class_getClassMethod : function (cls:_Class; name:SEL):Method; cdecl = nil;
class_getMethodImplementation : function (cls:_Class; name:SEL):IMP; cdecl = nil;
class_getMethodImplementation_stret : function (cls:_Class; name:SEL):IMP; cdecl = nil;
class_respondsToSelector : function (cls:_Class; sel:SEL):BOOL; cdecl = nil;
class_copyMethodList : function (cls:_Class; outCount:pdword):PMethod; cdecl = nil;
class_conformsToProtocol : function (cls:_Class; var protocol: Protocol):BOOL; cdecl = nil;
class_copyProtocolList : function (cls:_Class; var outCount: dword):PArrayPProtocol; cdecl = nil;
class_getProperty : function (cls:_Class; name: pchar): objc_property_t; cdecl = nil;
class_copyPropertyList : function (cls:_Class; var Count:dword):Pobjc_property_t; cdecl = nil;
class_getIvarLayout : function (cls:_Class):Pchar; cdecl = nil;
class_getWeakIvarLayout : function (cls:_Class):Pchar; cdecl = nil;
class_createInstance : function (cls:_Class; extraBytes:size_t):id; cdecl = nil;
objc_allocateClassPair : function (superclass:_Class; name:pchar; extraBytes:size_t):_Class; cdecl = nil;
objc_registerClassPair : procedure (cls:_Class); cdecl = nil;
objc_duplicateClass : function (original:_Class; name:pchar; extraBytes:size_t):_Class; cdecl = nil;
objc_disposeClassPair : procedure (cls:_Class); cdecl = nil;
class_addMethod : function (cls:_Class; name:SEL; imp:IMP; types:pchar):BOOL; cdecl = nil;
class_replaceMethod : function (cls:_Class; name:SEL; imp:IMP; types:pchar):IMP; cdecl = nil;
class_addIvar: function (cls:_Class; name:pchar; size:size_t; alignment:uint8_t; types:pchar):BOOL; cdecl = nil;
class_addProtocol : function (cls:_Class; protocol:pProtocol):BOOL; cdecl = nil;
class_setIvarLayout : procedure (cls:_Class; layout:pchar); cdecl = nil;
class_setWeakIvarLayout : procedure (cls:_Class; layout:pchar); cdecl = nil;
method_getName : function (m:Method):SEL; cdecl = nil;
method_getImplementation : function (m:Method):IMP; cdecl = nil;
method_getTypeEncoding : function (m:Method):Pchar; cdecl = nil;
method_getNumberOfArguments : function (m:Method):dword; cdecl = nil;
method_copyReturnType : function (m:Method):Pchar; cdecl = nil;
method_copyArgumentType : function (m:Method; index:dword):Pchar; cdecl = nil;
method_getReturnType : procedure (m:Method; dst:pchar; dst_len:size_t); cdecl = nil;
method_getArgumentType : procedure (m:Method; index:dword; dst:pchar; dst_len:size_t); cdecl = nil;
method_getDescription : function (m: Method) : Pobjc_method_description; cdecl = nil;
method_setImplementation: function (m:Method; imp:IMP):IMP; cdecl = nil;
method_exchangeImplementations : procedure (m1:Method; m2:Method); cdecl = nil;
ivar_getName : function (v:Ivar):Pchar; cdecl = nil;
ivar_getTypeEncoding : function (v:Ivar):Pchar; cdecl = nil;
ivar_getOffset : function (v:Ivar):ptrdiff_t; cdecl = nil;
property_getName :function (_property:objc_property_t):Pchar; cdecl = nil;
property_getAttributes : function (_property:objc_property_t):Pchar; cdecl = nil;
protocol_conformsToProtocol : function (proto:pProtocol; other:pProtocol):BOOL; cdecl = nil;
protocol_isEqual : function (proto:pProtocol; other:pProtocol):BOOL; cdecl = nil;
protocol_getMethodDescription : function (p: PProtocol; aSel: SEL; isRequiredMethod, isInstanceMethod: BOOL): objc_method_description; cdecl = nil;
protocol_copyMethodDescriptionList : function (p: PProtocol; isRequiredMethod, isInstanceMethod: BOOL ; var outCount: LongWord): Pobjc_method_description; cdecl = nil;
protocol_getProperty : function (proto:PProtocol; name:pchar; isRequiredProperty:BOOL; isInstanceProperty:BOOL):objc_property_t; cdecl = nil;
protocol_copyPropertyList : function (proto:PProtocol; outCount:pdword):Pobjc_property_t; cdecl = nil;
protocol_copyProtocolList : function (proto:PProtocol; outCount:pdword):PArrayPProtocol; cdecl = nil;
objc_copyImageNames : function (var outCount:dword): PPchar; cdecl = nil;
class_getImageName : function (cls:_Class):Pchar; cdecl = nil;
objc_copyClassNamesForImage : function (image:pchar; var outCount: Dword):PPchar; cdecl = nil;
sel_isEqual : function (lhs:SEL; rhs:SEL):BOOL; cdecl = nil;
objc_enumerationMutation : procedure (_para1:id); cdecl = nil;
objc_setEnumerationMutationHandler : procedure (handler:TMutationHandlerProc); cdecl = nil;
objc_setForwardHandler: procedure (fwd:pointer; fwd_stret:pointer); cdecl = nil;
{$WARNINGS OFF} // warning: cdecl'ared funtions have no high parameter
objc_msgSend : function (self: id; op: SEL; param3: array of const): id; cdecl = nil;
objc_msgSendSuper : function (super: pobjc_super; op: SEL; param3: array of const): id; cdecl = nil;
objc_msgSend_stret : procedure (stret: Pointer; self: id; op: SEL; param3: array of const); cdecl= nil;
objc_msgSend_stretreg : function (self: id; op: SEL; param3: array of const): id; cdecl= nil;
objc_msgSendSuper_stret : procedure (stret: Pointer; super: pobjc_super; op: SEL; param3: array of const); cdecl = nil;
objc_msgSend_fpret : function (self: id; op: SEL; param3: array of const): double; cdecl = nil;
{$WARNINGS ON}
method_invoke : function (receiver: id; m: Method {, ...}): id= nil;
method_invoke_stret : procedure (receiver: id; m: Method{ , ...})= nil;
objc_collect : procedure (options: LongWord); cdecl= nil;
objc_collectingEnabled : function : BOOL; cdecl= nil;
const
_C_ID = '@';
_C_CLASS = '#';
_C_SEL = ':';
_C_CHR = 'c';
_C_UCHR = 'C';
_C_SHT = 's';
_C_USHT = 'S';
_C_INT = 'i';
_C_UINT = 'I';
_C_LNG = 'l';
_C_ULNG = 'L';
_C_FLT = 'f';
_C_DBL = 'd';
_C_BFLD = 'b';
_C_VOID = 'v';
_C_UNDEF = '?';
_C_PTR = '^';
_C_CHARPTR = '*';
_C_ARY_B = '[';
_C_ARY_E = ']';
_C_UNION_B = '(';
_C_UNION_E = ')';
_C_STRUCT_B = '{';
_C_STRUCT_E = '}';
_C_PASOBJ = _C_PTR + _C_VOID;
_C_SELF_AND_SEL = '@:';
// objc-exception.h
// compiler reserves a setjmp buffer + 4 words as localExceptionData
type
Tobjc_exception_throw = procedure (exception: id); cdecl;
Tobjc_exception_try_enter = procedure (localExceptionData: Pointer); cdecl;
Tobjc_exception_try_exit = procedure (localExceptionData: Pointer); cdecl;
Tobjc_exception_extract = function (localExceptionData: Pointer): id; cdecl;
Tobjc_exception_match = function (exceptionClass:_Class; exception:id ): Integer; cdecl;
var
objc_exception_throw : Tobjc_exception_throw = nil;
objc_exception_try_enter : Tobjc_exception_try_enter = nil;
objc_exception_try_exit : Tobjc_exception_try_exit = nil;
objc_exception_extract : Tobjc_exception_extract = nil;
objc_exception_match : Tobjc_exception_match = nil;
type
pobjc_exception_functions_t = ^objc_exception_functions_t;
objc_exception_functions_t = packed record
version : Integer;
throw_exc : Tobjc_exception_throw; // version 0
try_enter : Tobjc_exception_try_enter; // version 0
try_exit : Tobjc_exception_try_exit; // version 0
extract : Tobjc_exception_extract; // version 0
match : Tobjc_exception_match; // version 0
end;
// get table; version tells how many
var
objc_exception_get_functions : procedure (var table: objc_exception_functions_t); cdecl = nil;
objc_exception_set_functions : procedure (table: pobjc_exception_functions_t); cdecl = nil;
// __LP64__ // 64-bit only functions
{
typedef id (*objc_exception_preprocessor)(id exception);
typedef int (*objc_exception_matcher)(Class catch_type, id exception);
typedef void (*objc_uncaught_exception_handler)(id exception);
typedef void (*objc_exception_handler)(id unused, void *context);
OBJC_EXPORT void objc_exception_throw(id exception);
OBJC_EXPORT void objc_exception_rethrow(void);
OBJC_EXPORT id objc_begin_catch(void *exc_buf);
OBJC_EXPORT void objc_end_catch(void);
OBJC_EXPORT uintptr_t objc_addExceptionHandler(objc_exception_handler fn, void *context);
OBJC_EXPORT void objc_removeExceptionHandler(uintptr_t token);
OBJC_EXPORT objc_exception_preprocessor objc_setExceptionPreprocessor(objc_exception_preprocessor fn);
OBJC_EXPORT objc_exception_matcher objc_setExceptionMatcher(objc_exception_matcher fn);
OBJC_EXPORT objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler fn);
}
// objc-sync.h
var
// Begin synchronizing on 'obj'.
// Allocates recursive pthread_mutex associated with 'obj' if needed.
// Returns OBJC_SYNC_SUCCESS once lock is acquired.
objc_sync_enter: function (obj: id): Integer; cdecl = nil;
// End synchronizing on 'obj'.
// Returns OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR
objc_sync_exit : function (obj: id) : Integer; cdecl = nil;
// Temporarily release lock on 'obj' and wait for another thread to notify on 'obj'
// Return OBJC_SYNC_SUCCESS, OBJC_SYNC_NOT_OWNING_THREAD_ERROR, OBJC_SYNC_TIMED_OUT
objc_sync_wait : function (obj: id; milliSecondsMaxWait: Int64): Integer; cdecl = nil;
// Wake up another thread waiting on 'obj'
// Return OBJC_SYNC_SUCCESS, OBJC_SYNC_NOT_OWNING_THREAD_ERROR
objc_sync_notify : function (obj: id): Integer; cdecl = nil;
// Wake up all threads waiting on 'obj'
// Return OBJC_SYNC_SUCCESS, OBJC_SYNC_NOT_OWNING_THREAD_ERROR
objc_sync_notifyAll : function (obj: id): Integer; cdecl = nil;
const
OBJC_SYNC_SUCCESS = 0;
OBJC_SYNC_NOT_OWNING_THREAD_ERROR = -1;
OBJC_SYNC_TIMED_OUT = -2;
OBJC_SYNC_NOT_INITIALIZED = -3;
// since exception handling does not change from version to version
// it's nice to make a common RTL loading function for exception functions.
// this proc, MUST BE called by run-time initialization proc!
function LoadDefaultObjCExepction(hnd: TLibHandle): Boolean;
function LoadDefaultObjCSync(hnd: TLibHandle): Boolean;
function LoadDefaultObjCMessaging(hnd: TLibHandle): Boolean;
implementation
function LoadDefaultObjCExepction(hnd: TLibHandle): Boolean;
begin
Result := hnd <> 0;
if not Result then Exit;
objc_exception_throw := Tobjc_exception_throw(GetProcedureAddress(hnd, 'objc_exception_throw'));
objc_exception_try_enter := Tobjc_exception_try_enter(GetProcedureAddress(hnd, 'objc_exception_try_enter'));
objc_exception_try_exit := Tobjc_exception_try_exit(GetProcedureAddress(hnd, 'objc_exception_try_exit'));
objc_exception_extract := Tobjc_exception_extract(GetProcedureAddress(hnd, 'objc_exception_extract'));
objc_exception_match := Tobjc_exception_match(GetProcedureAddress(hnd, 'objc_exception_match'));
end;
function LoadDefaultObjCSync(hnd: TLibHandle): Boolean;
begin
Result := hnd <> 0;
if not Result then Exit;
Pointer(objc_sync_enter) := GetProcedureAddress(hnd, 'objc_sync_enter');
Pointer(objc_sync_exit) := GetProcedureAddress(hnd, 'objc_sync_exit');
Pointer(objc_sync_wait) := GetProcedureAddress(hnd, 'objc_sync_wait');
Pointer(objc_sync_notify) := GetProcedureAddress(hnd, 'objc_sync_notify');
Pointer(objc_sync_notifyAll) := GetProcedureAddress(hnd, 'objc_sync_notifyAll');
end;
function LoadDefaultObjCMessaging(hnd: TLibHandle): Boolean;
begin
Pointer(objc_msgSend) := GetProcedureAddress(hnd, 'objc_msgSend');
Pointer(objc_msgSendSuper) := GetProcedureAddress(hnd, 'objc_msgSendSuper');
Pointer(objc_msgSend_stret) := GetProcedureAddress(hnd, 'objc_msgSend_stret');
Pointer(objc_msgSendSuper_stret) := GetProcedureAddress(hnd, 'objc_msgSendSuper_stret');
{$ifndef CPUPOWERPC} // arm also uses objc_msgSend_fpret?
Pointer(objc_msgSend_fpret) := GetProcedureAddress(hnd, 'objc_msgSend_fpret');
Pointer(objc_msgSend_stretreg) := GetProcedureAddress(hnd, 'objc_msgSend');
{$else}
Pointer(objc_msgSend_fpret) := GetProcedureAddress(hnd, 'objc_msgSend');
Pointer(objc_msgSend_stretreg) := GetProcedureAddress(hnd, 'objc_msgSend_stret');
{$endif}
Result := true;
end;
initialization
end.
|