objcrtl.pas 18 KB

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