objc1.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2009 by the Free Pascal development team
  4. This unit provides an interface to the Objective-C 1.0
  5. run time as defined by Apple
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit objc1;
  13. interface
  14. {$inline on}
  15. uses
  16. ctypes
  17. {$ifdef unix}
  18. ,unixtype
  19. {$endif}
  20. ;
  21. {$packrecords c}
  22. {$ifdef darwin}
  23. const
  24. libname = 'objc';
  25. {$linkframework Cocoa}
  26. {$define targetok}
  27. {$endif}
  28. {$ifndef targetok}
  29. {$error Add support for the current target to the objc1 unit }
  30. {$endif}
  31. const
  32. CLS_CLASS = $1;
  33. CLS_META = $2;
  34. type
  35. { make all opaque types assignment-incompatible with other typed pointers by
  36. declaring them as pointers to empty records
  37. WARNING: do NOT change the names, types or field names/types of these
  38. types, as many are used internally by the compiler.
  39. }
  40. { BOOL is one byte and uses 0/1, just like Pascal }
  41. BOOL = boolean;
  42. tobjc_class = record
  43. end;
  44. pobjc_class = ^tobjc_class;
  45. _Class = pobjc_class;
  46. objc_object = record
  47. isa: pobjc_class;
  48. end;
  49. id = ^objc_object;
  50. pobjc_object = id;
  51. _fpc_objc_sel_type = record
  52. end;
  53. SEL = ^_fpc_objc_sel_type;
  54. objc_method = record
  55. end;
  56. Pobjc_method = ^objc_method;
  57. Method = Pobjc_method;
  58. PMethod = ^Method;
  59. IMP = function(target: id; msg: SEL): id; varargs; cdecl;
  60. objc_super = record
  61. receiver: id;
  62. _class: pobjc_class;
  63. end;
  64. pobjc_super = ^objc_super;
  65. _fpc_objc_protocol_type = record
  66. end;
  67. pobjc_protocol = ^_fpc_objc_protocol_type;
  68. ppobjc_protocol = ^pobjc_protocol;
  69. objc_ivar = packed record
  70. end;
  71. Pobjc_ivar = ^objc_ivar;
  72. Ivar = Pobjc_ivar;
  73. PIvar = ^Ivar;
  74. { type that certainly will be returned by address }
  75. tdummyrecbyaddrresult = record
  76. a: array[0..1000] of shortstring;
  77. end;
  78. ptrdiff_t = ptrint;
  79. { sending messages }
  80. function objc_msgSend(self: id; op: SEL): id; cdecl; varargs; external libname;
  81. function objc_msgSendSuper(const super: pobjc_super; op: SEL): id; cdecl; varargs; external libname;
  82. { The following two are declared as procedures with the hidden result pointer
  83. as their first parameter. This corresponds to the declaration below as far
  84. as the code generator is concerned (and is easier to handle in the compiler). }
  85. function objc_msgSend_stret(self: id; op: SEL): tdummyrecbyaddrresult; cdecl; varargs; external libname;
  86. function objc_msgSendSuper_stret(const super: pobjc_super; op: SEL): tdummyrecbyaddrresult; cdecl; varargs; external libname;
  87. {$ifdef cpui386}
  88. function objc_msgSend_fpret (self: id; op: SEL): double; cdecl; varargs; external libname;
  89. {$else cpui386}
  90. function objc_msgSend_fpret (self: id; op: SEL): double; cdecl; varargs; external libname name 'objc_msgSend';
  91. {$endif cpui386}
  92. function sel_getName(sel: SEL): PChar; cdecl; external libname;
  93. function sel_registerName(str: PChar): SEL; cdecl; external libname;
  94. function object_getClassName(obj: id): PChar; cdecl; external libname;
  95. function object_getIndexedIvars(obj: id ): Pointer; cdecl; external libname;
  96. function sel_getUid(const str: PChar): SEL; cdecl; external libname;
  97. function object_copy(obj:id; size:size_t):id; cdecl; external libname;
  98. function object_dispose(obj:id):id; cdecl; external libname;
  99. function object_getClass(obj:id): pobjc_class; cdecl;
  100. function object_setClass(obj:id; cls: pobjc_class):pobjc_class; cdecl;
  101. function object_getIvar(obj:id; _ivar:Ivar):id; cdecl;
  102. procedure object_setIvar(obj:id; _ivar:Ivar; value:id); cdecl;
  103. function object_setInstanceVariable(obj:id; name:pchar; value:pointer):Ivar; cdecl; external libname;
  104. function object_getInstanceVariable(obj:id; name:pchar; var outValue: Pointer):Ivar; cdecl; external libname;
  105. function objc_getClass(name:pchar):id; cdecl; external libname;
  106. function objc_getMetaClass(name:pchar):id; cdecl; external libname;
  107. function objc_lookUpClass(name:pchar):id; cdecl; external libname;
  108. function objc_getClassList(buffer:pClass; bufferCount:cint):cint; cdecl; external libname;
  109. function objc_getProtocol(name:pchar): pobjc_protocol; cdecl; weakexternal libname;
  110. function objc_copyProtocolList(outCount:pdword):ppobjc_protocol; cdecl; weakexternal libname;
  111. function class_getName(cls:pobjc_class):PChar; cdecl; inline;
  112. function class_isMetaClass(cls:pobjc_class):BOOL; cdecl;
  113. function class_getSuperclass(cls:pobjc_class):pobjc_class; cdecl; inline;
  114. function class_getVersion(cls:pobjc_class):longint; cdecl; external libname;
  115. procedure class_setVersion(cls:pobjc_class; version:longint); cdecl; external libname;
  116. function class_getInstanceSize(cls:pobjc_class):size_t; cdecl; external libname;
  117. function class_getInstanceVariable(cls:pobjc_class; name:pchar):Ivar; cdecl; external libname;
  118. function class_getClassVariable(cls:pobjc_class; name:pchar):Ivar; cdecl; external libname;
  119. function class_copyIvarList(cls:pobjc_class; outCount:pdword):PIvar; cdecl; external libname;
  120. function class_getInstanceMethod(cls:pobjc_class; name:SEL):Method; cdecl; external libname;
  121. function class_getClassMethod(cls:pobjc_class; name:SEL):Method; cdecl; external libname;
  122. function class_getMethodImplementation(cls:pobjc_class; name:SEL):IMP; cdecl; external libname;
  123. function class_getMethodImplementation_stret(cls:pobjc_class; name:SEL):IMP; cdecl; external libname;
  124. function class_respondsToSelector(cls:pobjc_class; sel:SEL):BOOL; cdecl; external libname;
  125. function class_copyMethodList(cls:pobjc_class; outCount:pdword):PMethod; cdecl; external libname;
  126. function class_conformsToProtocol(cls:pobjc_class; var protocol: pobjc_protocol):BOOL; cdecl; external libname;
  127. function class_copyProtocolList(cls:pobjc_class; var outCount: dword):ppobjc_protocol; cdecl; external libname;
  128. function class_createInstance(cls:pobjc_class; extraBytes:size_t):id; cdecl; external libname;
  129. (*
  130. function objc_allocateClassPair(superclass:pobjc_class; name:pchar; extraBytes:size_t):pobjc_class; cdecl; external libname;
  131. procedure objc_registerClassPair(cls:pobjc_class); cdecl; external libname;
  132. function objc_duplicateClass(original:pobjc_class; name:pchar; extraBytes:size_t):pobjc_class; cdecl; external libname;
  133. procedure objc_disposeClassPair(cls:pobjc_class); cdecl; external libname;
  134. function class_addMethod(cls:pobjc_class; name:SEL; imp:IMP; types:pchar):BOOL; cdecl; external libname;
  135. function class_addIvar(cls:pobjc_class; name:pchar; size:size_t; alignment:uint8_t; types:pchar):BOOL; cdecl; external libname;
  136. function class_addProtocol(cls:pobjc_class; protocol:pProtocol):BOOL; cdecl; external libname;
  137. *)
  138. function method_getName(m:Method):SEL; cdecl; inline;
  139. function method_getImplementation(m:Method):IMP; cdecl; inline;
  140. function method_getTypeEncoding(m:Method):Pchar; cdecl; inline;
  141. function method_getNumberOfArguments(m:Method):dword; cdecl; external libname;
  142. (*
  143. function method_copyReturnType(m:Method):Pchar; cdecl; weakexternal libname;
  144. function method_copyArgumentType(m:Method; index:dword):Pchar; cdecl; weakexternal libname;
  145. procedure method_getReturnType(m:Method; dst:pchar; dst_len:size_t); cdecl; external libname;
  146. function method_setImplementation(m:Method; imp:IMP):IMP; cdecl; external libname;
  147. *)
  148. function ivar_getName(v:Ivar):Pchar; cdecl; inline;
  149. function ivar_getTypeEncoding(v:Ivar):Pchar; cdecl; inline;
  150. function ivar_getOffset(v:Ivar):ptrdiff_t; cdecl; inline;
  151. (*
  152. function sel_isEqual(lhs:SEL; rhs:SEL):BOOL; cdecl; external libname;
  153. *)
  154. implementation
  155. type
  156. {* Method Template }
  157. Pobjc_method1 = ^objc_method1;
  158. Method1 = Pobjc_method1;
  159. objc_method1 = packed record
  160. method_name : SEL;
  161. method_types : PChar;
  162. method_imp : IMP;
  163. end;
  164. Pobjc_method_list1 = ^objc_method_list1;
  165. PPobjc_method_list1 = ^Pobjc_method_list1;
  166. objc_method_list1 = packed record
  167. obsolete : Pobjc_method_list1;
  168. method_count : cint;
  169. {$ifdef __alpha__}
  170. space: cint;
  171. {$endif}
  172. method_list1 : array[0..0] of objc_method1; { variable length structure }
  173. end;
  174. {* Instance Variable Template}
  175. Pobjc_ivar1 = ^objc_ivar1;
  176. Ivar1 = Pobjc_ivar1;
  177. PIvar1 = ^Ivar1;
  178. objc_ivar1 = packed record
  179. ivar_name : PChar;
  180. ivar_type : PChar;
  181. ivar_offset : cint;
  182. {$ifdef __alpha__}
  183. space: cint;
  184. {$endif}
  185. end;
  186. Pobjc_ivar_list1 = ^objc_ivar_list1;
  187. objc_ivar_list1 = packed record
  188. ivar_count: cint;
  189. {$ifdef __alpha__}
  190. space: cint;
  191. {$endif}
  192. ivar_list: array[0..0] of objc_ivar1; { variable length structure }
  193. end;
  194. Pobjc_cache1 = ^objc_cache1;
  195. objc_cache1 = record
  196. mask : cuint; { total = mask + 1 }
  197. occupied : cuint;
  198. buckets : array[0..0] of Method1;
  199. end;
  200. Protocol1 = objc_object;
  201. Pobjc_protocol_list1 = ^objc_protocol_list1;
  202. objc_protocol_list1 = record
  203. next : Pobjc_protocol_list1;
  204. count : cint;
  205. list : array[0..0] of Protocol1;
  206. end;
  207. pobjc_class1 = ^objc_class1;
  208. objc_class1 = packed record
  209. isa : Pobjc_class1;
  210. super_class : Pobjc_class1;
  211. name : PChar;
  212. version : culong;
  213. info : culong;
  214. instance_size : culong;
  215. ivars : Pobjc_ivar_list1;
  216. methodLists : PPobjc_method_list1;
  217. cache : Pobjc_cache1;
  218. protocols : Pobjc_protocol_list1;
  219. end;
  220. Pid = ^id;
  221. function object_getClass(obj:id): pobjc_class; cdecl;
  222. begin
  223. if obj = nil then
  224. object_getClass := nil
  225. else
  226. begin
  227. object_getClass := pobjc_class(Pobjc_object(obj)^.isa);
  228. end;
  229. end;
  230. function object_setClass(obj:id; cls: pobjc_class): pobjc_class; cdecl;
  231. begin
  232. // can this be done in that way?
  233. object_setClass := pobjc_class(Pobjc_object(obj)^.isa);
  234. Pobjc_object(obj)^.isa := pobjc_class(cls);
  235. end;
  236. function object_getIvar(obj:id; _ivar:Ivar):id; cdecl;
  237. begin
  238. object_getIvar := nil;
  239. if not Assigned(obj) or
  240. not Assigned(_ivar) then
  241. Exit;
  242. object_getIvar := Pid(PtrUInt(obj) + ivar_getOffset(_ivar))^;
  243. end;
  244. procedure object_setIvar(obj:id; _ivar:Ivar; value:id); cdecl;
  245. begin
  246. if not Assigned(obj) or
  247. not Assigned(_ivar) then
  248. Exit;
  249. Pid(PtrUInt(obj) + ivar_getOffset(_ivar))^ := value;
  250. end;
  251. function class_getName(cls:pobjc_class):PChar; cdecl; inline;
  252. begin
  253. class_getName := pobjc_class1(cls)^.name;
  254. end;
  255. function class_getSuperclass(cls:pobjc_class):pobjc_class; cdecl; inline;
  256. begin
  257. class_getSuperclass := pobjc_class(pobjc_class1(cls)^.super_class);
  258. end;
  259. function class_isMetaClass(cls:_Class):BOOL; cdecl;
  260. begin
  261. class_isMetaClass := Assigned(cls) and (pobjc_class1(cls)^.Info = CLS_META);
  262. end;
  263. function method_getName(m:Method):SEL; cdecl; inline;
  264. begin
  265. method_getName := Method1(m)^.method_name;
  266. end;
  267. function method_getImplementation(m:Method):IMP; cdecl; inline;
  268. begin
  269. method_getImplementation := IMP(Method1(m)^.method_imp);
  270. end;
  271. function method_getTypeEncoding(m:Method):Pchar; cdecl; inline;
  272. begin
  273. method_getTypeEncoding := Method1(m)^.method_types;
  274. end;
  275. function ivar_getName(v:Ivar):Pchar; cdecl; inline;
  276. begin
  277. ivar_getName := IVar1(v)^.ivar_name;
  278. end;
  279. function ivar_getTypeEncoding(v:Ivar):Pchar; cdecl; inline;
  280. begin
  281. ivar_getTypeEncoding := IVar1(v)^.ivar_type;
  282. end;
  283. function ivar_getOffset(v:Ivar):ptrdiff_t; cdecl; inline;
  284. begin
  285. ivar_getOffset := ptrdiff_t(IVar1(v)^.ivar_offset);
  286. end;
  287. end.