objpas.inc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. This unit makes Free Pascal as much as possible Delphi compatible
  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. {****************************************************************************
  13. Internal Routines called from the Compiler
  14. ****************************************************************************}
  15. { the reverse order of the parameters make code generation easier }
  16. function fpc_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  17. begin
  18. fpc_do_is:=assigned(aobject) and assigned(aclass) and
  19. aobject.inheritsfrom(aclass);
  20. end;
  21. { the reverse order of the parameters make code generation easier }
  22. function fpc_do_as(aclass : tclass;aobject : tobject): tobject;[public,alias: 'FPC_DO_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  23. begin
  24. if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
  25. handleerrorframe(219,get_frame);
  26. result := aobject;
  27. end;
  28. {$ifndef HASINTF}
  29. { dummies for make cycle with 1.0.x }
  30. procedure fpc_intf_decr_ref(var i: pointer);saveregisters;[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  31. begin
  32. end;
  33. procedure fpc_intf_incr_ref(i: pointer);saveregisters;[public,alias: 'FPC_INTF_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  34. begin
  35. end;
  36. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
  37. begin
  38. end;
  39. function fpc_intf_as(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  40. begin
  41. end;
  42. function fpc_class_as_intf(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_CLASS_AS_INTF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  43. begin
  44. end;
  45. {$else HASINTF}
  46. { interface helpers }
  47. procedure fpc_intf_decr_ref(var i: pointer);saveregisters;[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  48. begin
  49. if assigned(i) then
  50. IUnknown(i)._Release;
  51. i:=nil;
  52. end;
  53. {$ifdef hascompilerproc}
  54. { local declaration for intf_decr_ref for local access }
  55. procedure intf_decr_ref(var i: pointer);saveregisters; [external name 'FPC_INTF_DECR_REF'];
  56. {$endif hascompilerproc}
  57. procedure fpc_intf_incr_ref(i: pointer);saveregisters;[public,alias: 'FPC_INTF_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  58. begin
  59. if assigned(i) then
  60. IUnknown(i)._AddRef;
  61. end;
  62. {$ifdef hascompilerproc}
  63. { local declaration of intf_incr_ref for local access }
  64. procedure intf_incr_ref(i: pointer);saveregisters; [external name 'FPC_INTF_INCR_REF'];
  65. {$endif hascompilerproc}
  66. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
  67. begin
  68. if assigned(S) then
  69. IUnknown(S)._AddRef;
  70. if assigned(D) then
  71. IUnknown(D)._Release;
  72. D:=S;
  73. end;
  74. function fpc_intf_as(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  75. const
  76. S_OK = 0;
  77. var
  78. tmpi: pointer; // _AddRef before _Release
  79. begin
  80. if assigned(S) then
  81. begin
  82. if IUnknown(S).QueryInterface(iid,tmpi)<>S_OK then
  83. handleerror(219);
  84. fpc_intf_as:=tmpi;
  85. end
  86. else
  87. fpc_intf_as:=nil;
  88. end;
  89. function fpc_class_as_intf(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_CLASS_AS_INTF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  90. const
  91. S_OK = 0;
  92. var
  93. tmpi: pointer; // _AddRef before _Release
  94. begin
  95. if assigned(S) then
  96. begin
  97. if not TObject(S).GetInterface(iid,tmpi) then
  98. handleerror(219);
  99. fpc_class_as_intf:=tmpi;
  100. end
  101. else
  102. fpc_class_as_intf:=nil;
  103. end;
  104. {$endif HASINTF}
  105. function aligntoptr(p : pointer) : pointer;
  106. begin
  107. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  108. if (ptrint(p) mod sizeof(ptrint))<>0 then
  109. inc(ptrint(p),sizeof(ptrint)-ptrint(p) mod sizeof(ptrint));
  110. result:=p;
  111. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  112. end;
  113. {****************************************************************************
  114. TOBJECT
  115. ****************************************************************************}
  116. constructor TObject.Create;
  117. begin
  118. end;
  119. destructor TObject.Destroy;
  120. begin
  121. end;
  122. procedure TObject.Free;
  123. begin
  124. // the call via self avoids a warning
  125. if self<>nil then
  126. self.destroy;
  127. end;
  128. class function TObject.InstanceSize : LongInt;
  129. begin
  130. InstanceSize:=plongint(pointer(self)+vmtInstanceSize)^;
  131. end;
  132. procedure InitInterfacePointers(objclass: tclass;instance : pointer);
  133. {$ifdef HASINTF}
  134. var
  135. intftable : pinterfacetable;
  136. i : longint;
  137. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  138. IOffset : longint;
  139. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  140. begin
  141. while assigned(objclass) do
  142. begin
  143. intftable:=pinterfacetable((pointer(objclass)+vmtIntfTable)^);
  144. if assigned(intftable) then
  145. for i:=0 to intftable^.EntryCount-1 do
  146. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  147. begin
  148. move(intftable^.Entries[i].IOffset,IOffset,sizeof(longint));
  149. move(pointer(intftable^.Entries[i].VTable),ppointer(@(PChar(instance)[IOffset]))^,sizeof(pointer));
  150. end;
  151. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  152. ppointer(@(PChar(instance)[intftable^.Entries[i].IOffset]))^:=
  153. pointer(intftable^.Entries[i].VTable);
  154. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  155. objclass:=pclass(pointer(objclass)+vmtParent)^;
  156. end;
  157. end;
  158. {$else HASINTF}
  159. begin
  160. end;
  161. {$endif HASINTF}
  162. class function TObject.InitInstance(instance : pointer) : tobject;
  163. begin
  164. { the size is saved at offset 0 }
  165. fillchar(instance^,plongint(pointer(self)+vmtInstanceSize)^,0);
  166. { insert VMT pointer into the new created memory area }
  167. { (in class methods self contains the VMT!) }
  168. ppointer(instance)^:=pointer(self);
  169. {$ifdef HASINTF}
  170. InitInterfacePointers(self,instance);
  171. {$endif HASINTF}
  172. InitInstance:=TObject(Instance);
  173. end;
  174. class function TObject.ClassParent : tclass;
  175. begin
  176. { type of self is class of tobject => it points to the vmt }
  177. { the parent vmt is saved at offset vmtParent }
  178. classparent:=pclass(pointer(self)+vmtParent)^;
  179. end;
  180. class function TObject.NewInstance : tobject;
  181. var
  182. p : pointer;
  183. begin
  184. getmem(p,plongint(pointer(self)+vmtInstanceSize)^);
  185. if p <> nil then
  186. InitInstance(p);
  187. NewInstance:=TObject(p);
  188. end;
  189. procedure TObject.FreeInstance;
  190. begin
  191. CleanupInstance;
  192. FreeMem(Pointer(Self));
  193. end;
  194. class function TObject.ClassType : TClass;
  195. begin
  196. ClassType:=TClass(Pointer(Self))
  197. end;
  198. type
  199. tmethodnamerec = packed record
  200. name : pshortstring;
  201. addr : pointer;
  202. end;
  203. tmethodnametable = packed record
  204. count : dword;
  205. entries : packed array[0..0] of tmethodnamerec;
  206. end;
  207. pmethodnametable = ^tmethodnametable;
  208. class function TObject.MethodAddress(const name : shortstring) : pointer;
  209. var
  210. UName : ShortString;
  211. methodtable : pmethodnametable;
  212. i : dword;
  213. vmt : tclass;
  214. begin
  215. UName := UpCase(name);
  216. vmt:=self;
  217. while assigned(vmt) do
  218. begin
  219. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  220. if assigned(methodtable) then
  221. begin
  222. for i:=0 to methodtable^.count-1 do
  223. if UpCase(methodtable^.entries[i].name^)=UName then
  224. begin
  225. MethodAddress:=methodtable^.entries[i].addr;
  226. exit;
  227. end;
  228. end;
  229. vmt:=pclass(pointer(vmt)+vmtParent)^;
  230. end;
  231. MethodAddress:=nil;
  232. end;
  233. class function TObject.MethodName(address : pointer) : shortstring;
  234. var
  235. methodtable : pmethodnametable;
  236. i : dword;
  237. vmt : tclass;
  238. begin
  239. vmt:=self;
  240. while assigned(vmt) do
  241. begin
  242. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  243. if assigned(methodtable) then
  244. begin
  245. for i:=0 to methodtable^.count-1 do
  246. if methodtable^.entries[i].addr=address then
  247. begin
  248. MethodName:=methodtable^.entries[i].name^;
  249. exit;
  250. end;
  251. end;
  252. vmt:=pclass(pointer(vmt)+vmtParent)^;
  253. end;
  254. MethodName:='';
  255. end;
  256. function TObject.FieldAddress(const name : shortstring) : pointer;
  257. type
  258. PFieldInfo = ^TFieldInfo;
  259. TFieldInfo = packed record
  260. FieldOffset: LongWord;
  261. ClassTypeIndex: Word;
  262. Name: ShortString;
  263. end;
  264. PFieldTable = ^TFieldTable;
  265. TFieldTable = packed record
  266. FieldCount: Word;
  267. ClassTable: Pointer;
  268. { Fields: array[Word] of TFieldInfo; Elements have variant size! }
  269. end;
  270. var
  271. UName: ShortString;
  272. CurClassType: TClass;
  273. FieldTable: PFieldTable;
  274. FieldInfo: PFieldInfo;
  275. i: Integer;
  276. begin
  277. if Length(name) > 0 then
  278. begin
  279. UName := UpCase(name);
  280. CurClassType := ClassType;
  281. while CurClassType <> nil do
  282. begin
  283. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  284. if FieldTable <> nil then
  285. begin
  286. FieldInfo := PFieldInfo(Pointer(FieldTable) + 6);
  287. for i := 0 to FieldTable^.FieldCount - 1 do
  288. begin
  289. if UpCase(FieldInfo^.Name) = UName then
  290. begin
  291. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  292. exit;
  293. end;
  294. Inc(Pointer(FieldInfo), 7 + Length(FieldInfo^.Name));
  295. end;
  296. end;
  297. { Try again with the parent class type }
  298. CurClassType:=pclass(pointer(CurClassType)+vmtParent)^;
  299. end;
  300. end;
  301. fieldaddress:=nil;
  302. end;
  303. function TObject.SafeCallException(exceptobject : tobject;
  304. exceptaddr : pointer) : longint;
  305. begin
  306. safecallexception:=0;
  307. end;
  308. class function TObject.ClassInfo : pointer;
  309. begin
  310. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  311. end;
  312. class function TObject.ClassName : ShortString;
  313. begin
  314. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  315. end;
  316. class function TObject.ClassNameIs(const name : string) : boolean;
  317. begin
  318. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  319. end;
  320. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  321. var
  322. vmt : tclass;
  323. begin
  324. vmt:=self;
  325. while assigned(vmt) do
  326. begin
  327. if vmt=aclass then
  328. begin
  329. InheritsFrom:=true;
  330. exit;
  331. end;
  332. vmt:=pclass(pointer(vmt)+vmtParent)^;
  333. end;
  334. InheritsFrom:=false;
  335. end;
  336. class function TObject.stringmessagetable : pstringmessagetable;
  337. type
  338. pdword = ^dword;
  339. begin
  340. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  341. end;
  342. type
  343. tmessagehandler = procedure(var msg) of object;
  344. tmessagehandlerrec = packed record
  345. proc : pointer;
  346. obj : pointer;
  347. end;
  348. procedure TObject.Dispatch(var message);
  349. type
  350. tmsgtable = packed record
  351. index : dword;
  352. method : pointer;
  353. end;
  354. pmsgtable = ^tmsgtable;
  355. var
  356. index : dword;
  357. count,i : longint;
  358. msgtable : pmsgtable;
  359. p : pointer;
  360. vmt : tclass;
  361. msghandler : tmessagehandler;
  362. begin
  363. index:=dword(message);
  364. vmt:=ClassType;
  365. while assigned(vmt) do
  366. begin
  367. // See if we have messages at all in this class.
  368. p:=pointer(vmt)+vmtDynamicTable;
  369. If Assigned(p) and (Pdword(p)^<>0) then
  370. begin
  371. msgtable:=pmsgtable(PtrInt(p^)+4);
  372. count:=pdword(p^)^;
  373. end
  374. else
  375. Count:=0;
  376. { later, we can implement a binary search here }
  377. for i:=0 to count-1 do
  378. begin
  379. if index=msgtable[i].index then
  380. begin
  381. p:=msgtable[i].method;
  382. tmessagehandlerrec(msghandler).proc:=p;
  383. tmessagehandlerrec(msghandler).obj:=self;
  384. msghandler(message);
  385. exit;
  386. end;
  387. end;
  388. vmt:=pclass(pointer(vmt)+vmtParent)^;
  389. end;
  390. DefaultHandler(message);
  391. end;
  392. procedure TObject.DispatchStr(var message);
  393. type
  394. PSizeUInt = ^SizeUInt;
  395. var
  396. name : shortstring;
  397. count,i : longint;
  398. msgstrtable : pmsgstrtable;
  399. p : pointer;
  400. vmt : tclass;
  401. msghandler : tmessagehandler;
  402. begin
  403. name:=pshortstring(@message)^;
  404. vmt:=ClassType;
  405. while assigned(vmt) do
  406. begin
  407. p:=(pointer(vmt)+vmtMsgStrPtr);
  408. If (P<>Nil) and (PDWord(P)^<>0) then
  409. begin
  410. count:=pdword(PSizeUInt(p)^)^;
  411. msgstrtable:=pmsgstrtable(PSizeUInt(P)^+4);
  412. end
  413. else
  414. Count:=0;
  415. { later, we can implement a binary search here }
  416. for i:=0 to count-1 do
  417. begin
  418. if name=msgstrtable[i].name^ then
  419. begin
  420. p:=msgstrtable[i].method;
  421. tmessagehandlerrec(msghandler).proc:=p;
  422. tmessagehandlerrec(msghandler).obj:=self;
  423. msghandler(message);
  424. exit;
  425. end;
  426. end;
  427. vmt:=pclass(pointer(vmt)+vmtParent)^;
  428. end;
  429. DefaultHandlerStr(message);
  430. end;
  431. procedure TObject.DefaultHandler(var message);
  432. begin
  433. end;
  434. procedure TObject.DefaultHandlerStr(var message);
  435. begin
  436. end;
  437. procedure TObject.CleanupInstance;
  438. Type
  439. TRecElem = Record
  440. Info : Pointer;
  441. Offset : Longint;
  442. end;
  443. TRecElemArray = Array[1..Maxint] of TRecElem;
  444. PRecRec = ^TRecRec;
  445. TRecRec = record
  446. Size,Count : Longint;
  447. Elements : TRecElemArray;
  448. end;
  449. var
  450. vmt : tclass;
  451. temp : pbyte;
  452. count,
  453. i : longint;
  454. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  455. recelem : TRecElem;
  456. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  457. begin
  458. vmt:=ClassType;
  459. while vmt<>nil do
  460. begin
  461. { This need to be included here, because Finalize()
  462. has should support for tkClass }
  463. Temp:=Pointer((Pointer(vmt)+vmtInitTable)^);
  464. if Assigned(Temp) then
  465. begin
  466. inc(Temp);
  467. I:=Temp^;
  468. inc(temp,I+1); // skip name string;
  469. {$ifdef FPC_ALIGNSRTTI}
  470. temp:=aligntoptr(temp);
  471. {$endif FPC_ALIGNSRTTI}
  472. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  473. move(PRecRec(Temp)^.Count,Count,sizeof(Count));
  474. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  475. Count:=PRecRec(Temp)^.Count; // get element Count
  476. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  477. For I:=1 to count do
  478. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  479. begin
  480. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(RecElem));
  481. With RecElem do
  482. int_Finalize (pointer(self)+Offset,Info);
  483. end;
  484. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  485. With PRecRec(Temp)^.elements[I] do
  486. int_Finalize (pointer(self)+Offset,Info);
  487. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  488. end;
  489. vmt:=pclass(pointer(vmt)+vmtParent)^;
  490. end;
  491. end;
  492. procedure TObject.AfterConstruction;
  493. begin
  494. end;
  495. procedure TObject.BeforeDestruction;
  496. begin
  497. end;
  498. {$ifdef HASINTF}
  499. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  500. begin
  501. IsGUIDEqual:=
  502. (guid1.D1=guid2.D1) and
  503. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  504. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  505. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  506. end;
  507. function TObject.getinterface(const iid : tguid;out obj) : boolean;
  508. var
  509. IEntry: pinterfaceentry;
  510. begin
  511. IEntry:=getinterfaceentry(iid);
  512. if Assigned(IEntry) then begin
  513. PPointer(@obj)^:=Pointer(Self)+IEntry^.IOffset;
  514. intf_incr_ref(pointer(obj)); { it must be an com interface }
  515. getinterface:=True;
  516. end
  517. else begin
  518. PPointer(@Obj)^:=nil;
  519. getinterface:=False;
  520. end;
  521. end;
  522. function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
  523. var
  524. IEntry: pinterfaceentry;
  525. begin
  526. IEntry:=getinterfaceentrybystr(iidstr);
  527. if Assigned(IEntry) then begin
  528. PPointer(@obj)^:=Pointer(Self)+IEntry^.IOffset;
  529. if Assigned(IEntry^.iid) then { for Com interfaces }
  530. intf_incr_ref(pointer(obj));
  531. getinterfacebystr:=True;
  532. end
  533. else begin
  534. PPointer(@Obj)^:=nil;
  535. getinterfacebystr:=False;
  536. end;
  537. end;
  538. class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
  539. var
  540. i: integer;
  541. intftable: pinterfacetable;
  542. Res: pinterfaceentry;
  543. begin
  544. getinterfaceentry:=nil;
  545. intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  546. if assigned(intftable) then begin
  547. i:=intftable^.EntryCount;
  548. Res:=@intftable^.Entries[0];
  549. while (i>0) and
  550. not (assigned(Res^.iid) and IsGUIDEqual(Res^.iid^,iid)) do begin
  551. inc(Res);
  552. dec(i);
  553. end;
  554. if (i>0) then
  555. getinterfaceentry:=Res;
  556. end;
  557. if (getinterfaceentry=nil)and not(classparent=nil) then
  558. getinterfaceentry:=classparent.getinterfaceentry(iid)
  559. end;
  560. class function TObject.getinterfaceentrybystr(const iidstr : string) : pinterfaceentry;
  561. var
  562. i: integer;
  563. intftable: pinterfacetable;
  564. Res: pinterfaceentry;
  565. begin
  566. getinterfaceentrybystr:=nil;
  567. intftable:=getinterfacetable;
  568. if assigned(intftable) then begin
  569. i:=intftable^.EntryCount;
  570. Res:=@intftable^.Entries[0];
  571. while (i>0) and (Res^.iidstr^<>iidstr) do begin
  572. inc(Res);
  573. dec(i);
  574. end;
  575. if (i>0) then
  576. getinterfaceentrybystr:=Res;
  577. end;
  578. if (getinterfaceentrybystr=nil)and not(classparent=nil) then
  579. getinterfaceentrybystr:=classparent.getinterfaceentrybystr(iidstr)
  580. end;
  581. class function TObject.getinterfacetable : pinterfacetable;
  582. begin
  583. getinterfacetable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  584. end;
  585. {****************************************************************************
  586. TINTERFACEDOBJECT
  587. ****************************************************************************}
  588. function TInterfacedObject.QueryInterface(
  589. const iid : tguid;out obj) : longint;stdcall;
  590. begin
  591. if getinterface(iid,obj) then
  592. result:=0
  593. else
  594. result:=longint($80004002);
  595. end;
  596. function TInterfacedObject._AddRef : longint;stdcall;
  597. begin
  598. inclocked(frefcount);
  599. _addref:=frefcount;
  600. end;
  601. function TInterfacedObject._Release : longint;stdcall;
  602. begin
  603. if declocked(frefcount) then
  604. begin
  605. destroy;
  606. _Release:=0;
  607. end
  608. else
  609. _Release:=frefcount;
  610. end;
  611. procedure TInterfacedObject.AfterConstruction;
  612. begin
  613. { we need to fix the refcount we forced in newinstance }
  614. { further, it must be done in a thread safe way }
  615. declocked(frefcount);
  616. end;
  617. procedure TInterfacedObject.BeforeDestruction;
  618. begin
  619. if frefcount<>0 then
  620. HandleError(204);
  621. end;
  622. class function TInterfacedObject.NewInstance : TObject;
  623. begin
  624. NewInstance:=inherited NewInstance;
  625. TInterfacedObject(NewInstance).frefcount:=1;
  626. end;
  627. {$endif HASINTF}
  628. {****************************************************************************
  629. Exception Support
  630. ****************************************************************************}
  631. {$i except.inc}
  632. {****************************************************************************
  633. Initialize
  634. ****************************************************************************}
  635. {
  636. $Log$
  637. Revision 1.40 2004-10-05 20:21:23 florian
  638. * bootstrapping with rtti alignment fixed
  639. Revision 1.39 2004/10/04 21:26:16 florian
  640. * rtti alignment fixed
  641. Revision 1.38 2004/04/29 21:33:22 florian
  642. * fixed tobject.dispatch for 64 bit cpus
  643. Revision 1.37 2004/04/28 20:48:20 peter
  644. * ordinal-pointer conversions fixed
  645. Revision 1.36 2004/03/22 22:19:36 florian
  646. * more alignment fixes
  647. Revision 1.35 2004/03/21 22:41:29 florian
  648. * CleanupInstance takes now care of FPC_REQUIRES_PROPER_ALIGNMENT
  649. Revision 1.34 2004/02/26 16:19:01 peter
  650. * tkclass removed from finalize()
  651. * cleanupinstance now parses the tkclass rtti entry itself and
  652. calls finalize() for the rtti members
  653. Revision 1.33 2003/07/19 11:19:07 michael
  654. + fix from Ivan Shikhalev for QueryInterface to return ancestor methods
  655. Revision 1.32 2003/05/01 08:05:23 florian
  656. * started to make the rtl 64 bit save by introducing SizeInt and SizeUInt (similar to size_t of C)
  657. Revision 1.31 2003/03/17 20:55:58 peter
  658. * ClassType changed to class method
  659. Revision 1.30 2002/10/19 15:53:20 peter
  660. * 'inlined' some more calls
  661. Revision 1.29 2002/10/15 19:29:49 peter
  662. * manual inline classparent calls in the loops
  663. Revision 1.28 2002/10/11 14:05:21 florian
  664. * initinterfacepointers improved
  665. Revision 1.27 2002/09/07 15:07:46 peter
  666. * old logs removed and tabs fixed
  667. Revision 1.26 2002/09/07 11:08:58 carl
  668. - remove logs
  669. Revision 1.25 2002/08/31 13:11:11 florian
  670. * several fixes for Linux/PPC compilation
  671. }