objpas.inc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  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);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  31. begin
  32. end;
  33. procedure fpc_intf_incr_ref(i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[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);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[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);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif} [external name 'FPC_INTF_DECR_REF'];
  56. {$endif hascompilerproc}
  57. procedure fpc_intf_incr_ref(i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[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);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif} [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. {****************************************************************************
  106. TOBJECT
  107. ****************************************************************************}
  108. constructor TObject.Create;
  109. begin
  110. end;
  111. destructor TObject.Destroy;
  112. begin
  113. end;
  114. procedure TObject.Free;
  115. begin
  116. // the call via self avoids a warning
  117. if self<>nil then
  118. self.destroy;
  119. end;
  120. class function TObject.InstanceSize : LongInt;
  121. begin
  122. InstanceSize:=plongint(pointer(self)+vmtInstanceSize)^;
  123. end;
  124. procedure InitInterfacePointers(objclass: tclass;instance : pointer);
  125. {$ifdef HASINTF}
  126. var
  127. intftable : pinterfacetable;
  128. i : longint;
  129. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  130. IOffset : longint;
  131. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  132. begin
  133. while assigned(objclass) do
  134. begin
  135. intftable:=pinterfacetable((pointer(objclass)+vmtIntfTable)^);
  136. if assigned(intftable) then
  137. for i:=0 to intftable^.EntryCount-1 do
  138. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  139. begin
  140. move(intftable^.Entries[i].IOffset,IOffset,sizeof(longint));
  141. move(pointer(intftable^.Entries[i].VTable),ppointer(@(PChar(instance)[IOffset]))^,sizeof(pointer));
  142. end;
  143. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  144. ppointer(@(PChar(instance)[intftable^.Entries[i].IOffset]))^:=
  145. pointer(intftable^.Entries[i].VTable);
  146. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  147. objclass:=pclass(pointer(objclass)+vmtParent)^;
  148. end;
  149. end;
  150. {$else HASINTF}
  151. begin
  152. end;
  153. {$endif HASINTF}
  154. class function TObject.InitInstance(instance : pointer) : tobject;
  155. begin
  156. { the size is saved at offset 0 }
  157. fillchar(instance^,plongint(pointer(self)+vmtInstanceSize)^,0);
  158. { insert VMT pointer into the new created memory area }
  159. { (in class methods self contains the VMT!) }
  160. ppointer(instance)^:=pointer(self);
  161. {$ifdef HASINTF}
  162. InitInterfacePointers(self,instance);
  163. {$endif HASINTF}
  164. InitInstance:=TObject(Instance);
  165. end;
  166. class function TObject.ClassParent : tclass;
  167. begin
  168. { type of self is class of tobject => it points to the vmt }
  169. { the parent vmt is saved at offset vmtParent }
  170. classparent:=pclass(pointer(self)+vmtParent)^;
  171. end;
  172. class function TObject.NewInstance : tobject;
  173. var
  174. p : pointer;
  175. begin
  176. getmem(p,plongint(pointer(self)+vmtInstanceSize)^);
  177. if p <> nil then
  178. InitInstance(p);
  179. NewInstance:=TObject(p);
  180. end;
  181. procedure TObject.FreeInstance;
  182. begin
  183. CleanupInstance;
  184. FreeMem(Pointer(Self));
  185. end;
  186. class function TObject.ClassType : TClass;
  187. begin
  188. ClassType:=TClass(Pointer(Self))
  189. end;
  190. type
  191. tmethodnamerec = packed record
  192. name : pshortstring;
  193. addr : pointer;
  194. end;
  195. tmethodnametable = packed record
  196. count : dword;
  197. entries : packed array[0..0] of tmethodnamerec;
  198. end;
  199. pmethodnametable = ^tmethodnametable;
  200. class function TObject.MethodAddress(const name : shortstring) : pointer;
  201. var
  202. UName : ShortString;
  203. methodtable : pmethodnametable;
  204. i : dword;
  205. vmt : tclass;
  206. begin
  207. UName := UpCase(name);
  208. vmt:=self;
  209. while assigned(vmt) do
  210. begin
  211. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  212. if assigned(methodtable) then
  213. begin
  214. for i:=0 to methodtable^.count-1 do
  215. if UpCase(methodtable^.entries[i].name^)=UName then
  216. begin
  217. MethodAddress:=methodtable^.entries[i].addr;
  218. exit;
  219. end;
  220. end;
  221. vmt:=pclass(pointer(vmt)+vmtParent)^;
  222. end;
  223. MethodAddress:=nil;
  224. end;
  225. class function TObject.MethodName(address : pointer) : shortstring;
  226. var
  227. methodtable : pmethodnametable;
  228. i : dword;
  229. vmt : tclass;
  230. begin
  231. vmt:=self;
  232. while assigned(vmt) do
  233. begin
  234. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  235. if assigned(methodtable) then
  236. begin
  237. for i:=0 to methodtable^.count-1 do
  238. if methodtable^.entries[i].addr=address then
  239. begin
  240. MethodName:=methodtable^.entries[i].name^;
  241. exit;
  242. end;
  243. end;
  244. vmt:=pclass(pointer(vmt)+vmtParent)^;
  245. end;
  246. MethodName:='';
  247. end;
  248. function TObject.FieldAddress(const name : shortstring) : pointer;
  249. type
  250. PFieldInfo = ^TFieldInfo;
  251. TFieldInfo = packed record
  252. FieldOffset: LongWord;
  253. ClassTypeIndex: Word;
  254. Name: ShortString;
  255. end;
  256. PFieldTable = ^TFieldTable;
  257. TFieldTable = packed record
  258. FieldCount: Word;
  259. ClassTable: Pointer;
  260. { Fields: array[Word] of TFieldInfo; Elements have variant size! }
  261. end;
  262. var
  263. UName: ShortString;
  264. CurClassType: TClass;
  265. FieldTable: PFieldTable;
  266. FieldInfo: PFieldInfo;
  267. i: Integer;
  268. begin
  269. if Length(name) > 0 then
  270. begin
  271. UName := UpCase(name);
  272. CurClassType := ClassType;
  273. while CurClassType <> nil do
  274. begin
  275. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  276. if FieldTable <> nil then
  277. begin
  278. FieldInfo := PFieldInfo(Pointer(FieldTable) + 6);
  279. for i := 0 to FieldTable^.FieldCount - 1 do
  280. begin
  281. if UpCase(FieldInfo^.Name) = UName then
  282. begin
  283. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  284. exit;
  285. end;
  286. Inc(Pointer(FieldInfo), 7 + Length(FieldInfo^.Name));
  287. end;
  288. end;
  289. { Try again with the parent class type }
  290. CurClassType:=pclass(pointer(CurClassType)+vmtParent)^;
  291. end;
  292. end;
  293. fieldaddress:=nil;
  294. end;
  295. function TObject.SafeCallException(exceptobject : tobject;
  296. exceptaddr : pointer) : longint;
  297. begin
  298. safecallexception:=0;
  299. end;
  300. class function TObject.ClassInfo : pointer;
  301. begin
  302. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  303. end;
  304. class function TObject.ClassName : ShortString;
  305. begin
  306. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  307. end;
  308. class function TObject.ClassNameIs(const name : string) : boolean;
  309. begin
  310. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  311. end;
  312. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  313. var
  314. vmt : tclass;
  315. begin
  316. vmt:=self;
  317. while assigned(vmt) do
  318. begin
  319. if vmt=aclass then
  320. begin
  321. InheritsFrom:=true;
  322. exit;
  323. end;
  324. vmt:=pclass(pointer(vmt)+vmtParent)^;
  325. end;
  326. InheritsFrom:=false;
  327. end;
  328. class function TObject.stringmessagetable : pstringmessagetable;
  329. type
  330. pdword = ^dword;
  331. begin
  332. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  333. end;
  334. type
  335. tmessagehandler = procedure(var msg) of object;
  336. tmessagehandlerrec = packed record
  337. proc : pointer;
  338. obj : pointer;
  339. end;
  340. procedure TObject.Dispatch(var message);
  341. type
  342. tmsgtable = packed record
  343. index : dword;
  344. method : pointer;
  345. end;
  346. pmsgtable = ^tmsgtable;
  347. var
  348. index : dword;
  349. count,i : longint;
  350. msgtable : pmsgtable;
  351. p : pointer;
  352. vmt : tclass;
  353. msghandler : tmessagehandler;
  354. begin
  355. index:=dword(message);
  356. vmt:=ClassType;
  357. while assigned(vmt) do
  358. begin
  359. // See if we have messages at all in this class.
  360. p:=pointer(vmt)+vmtDynamicTable;
  361. If Assigned(p) and (Pdword(p)^<>0) then
  362. begin
  363. msgtable:=pmsgtable(PtrInt(p^)+4);
  364. count:=pdword(p^)^;
  365. end
  366. else
  367. Count:=0;
  368. { later, we can implement a binary search here }
  369. for i:=0 to count-1 do
  370. begin
  371. if index=msgtable[i].index then
  372. begin
  373. p:=msgtable[i].method;
  374. tmessagehandlerrec(msghandler).proc:=p;
  375. tmessagehandlerrec(msghandler).obj:=self;
  376. msghandler(message);
  377. exit;
  378. end;
  379. end;
  380. vmt:=pclass(pointer(vmt)+vmtParent)^;
  381. end;
  382. DefaultHandler(message);
  383. end;
  384. procedure TObject.DispatchStr(var message);
  385. type
  386. PSizeUInt = ^SizeUInt;
  387. var
  388. name : shortstring;
  389. count,i : longint;
  390. msgstrtable : pmsgstrtable;
  391. p : pointer;
  392. vmt : tclass;
  393. msghandler : tmessagehandler;
  394. begin
  395. name:=pshortstring(@message)^;
  396. vmt:=ClassType;
  397. while assigned(vmt) do
  398. begin
  399. p:=(pointer(vmt)+vmtMsgStrPtr);
  400. If (P<>Nil) and (PDWord(P)^<>0) then
  401. begin
  402. count:=pdword(PSizeUInt(p)^)^;
  403. msgstrtable:=pmsgstrtable(PSizeUInt(P)^+4);
  404. end
  405. else
  406. Count:=0;
  407. { later, we can implement a binary search here }
  408. for i:=0 to count-1 do
  409. begin
  410. if name=msgstrtable[i].name^ then
  411. begin
  412. p:=msgstrtable[i].method;
  413. tmessagehandlerrec(msghandler).proc:=p;
  414. tmessagehandlerrec(msghandler).obj:=self;
  415. msghandler(message);
  416. exit;
  417. end;
  418. end;
  419. vmt:=pclass(pointer(vmt)+vmtParent)^;
  420. end;
  421. DefaultHandlerStr(message);
  422. end;
  423. procedure TObject.DefaultHandler(var message);
  424. begin
  425. end;
  426. procedure TObject.DefaultHandlerStr(var message);
  427. begin
  428. end;
  429. procedure TObject.CleanupInstance;
  430. Type
  431. TRecElem = packed Record
  432. Info : Pointer;
  433. Offset : Longint;
  434. end;
  435. TRecElemArray = packed array[1..Maxint] of TRecElem;
  436. PRecRec = ^TRecRec;
  437. TRecRec = record
  438. Size,Count : Longint;
  439. Elements : TRecElemArray;
  440. end;
  441. var
  442. vmt : tclass;
  443. temp : pbyte;
  444. count,
  445. i : longint;
  446. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  447. recelem : TRecElem;
  448. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  449. begin
  450. vmt:=ClassType;
  451. while vmt<>nil do
  452. begin
  453. { This need to be included here, because Finalize()
  454. has should support for tkClass }
  455. Temp:=Pointer((Pointer(vmt)+vmtInitTable)^);
  456. if Assigned(Temp) then
  457. begin
  458. inc(Temp);
  459. I:=Temp^;
  460. inc(temp,I+1); // skip name string;
  461. {$ifdef FPC_ALIGNSRTTI}
  462. temp:=aligntoptr(temp);
  463. {$endif FPC_ALIGNSRTTI}
  464. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  465. move(PRecRec(Temp)^.Count,Count,sizeof(Count));
  466. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  467. Count:=PRecRec(Temp)^.Count; // get element Count
  468. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  469. For I:=1 to count do
  470. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  471. begin
  472. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(RecElem));
  473. With RecElem do
  474. int_Finalize (pointer(self)+Offset,Info);
  475. end;
  476. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  477. With PRecRec(Temp)^.elements[I] do
  478. int_Finalize (pointer(self)+Offset,Info);
  479. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  480. end;
  481. vmt:=pclass(pointer(vmt)+vmtParent)^;
  482. end;
  483. end;
  484. procedure TObject.AfterConstruction;
  485. begin
  486. end;
  487. procedure TObject.BeforeDestruction;
  488. begin
  489. end;
  490. {$ifdef HASINTF}
  491. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  492. begin
  493. IsGUIDEqual:=
  494. (guid1.D1=guid2.D1) and
  495. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  496. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  497. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  498. end;
  499. function TObject.getinterface(const iid : tguid;out obj) : boolean;
  500. var
  501. IEntry: pinterfaceentry;
  502. begin
  503. IEntry:=getinterfaceentry(iid);
  504. if Assigned(IEntry) then begin
  505. PPointer(@obj)^:=Pointer(Self)+IEntry^.IOffset;
  506. intf_incr_ref(pointer(obj)); { it must be an com interface }
  507. getinterface:=True;
  508. end
  509. else begin
  510. PPointer(@Obj)^:=nil;
  511. getinterface:=False;
  512. end;
  513. end;
  514. function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
  515. var
  516. IEntry: pinterfaceentry;
  517. begin
  518. IEntry:=getinterfaceentrybystr(iidstr);
  519. if Assigned(IEntry) then begin
  520. PPointer(@obj)^:=Pointer(Self)+IEntry^.IOffset;
  521. if Assigned(IEntry^.iid) then { for Com interfaces }
  522. intf_incr_ref(pointer(obj));
  523. getinterfacebystr:=True;
  524. end
  525. else begin
  526. PPointer(@Obj)^:=nil;
  527. getinterfacebystr:=False;
  528. end;
  529. end;
  530. class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
  531. var
  532. i: integer;
  533. intftable: pinterfacetable;
  534. Res: pinterfaceentry;
  535. begin
  536. getinterfaceentry:=nil;
  537. intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  538. if assigned(intftable) then begin
  539. i:=intftable^.EntryCount;
  540. Res:=@intftable^.Entries[0];
  541. while (i>0) and
  542. not (assigned(Res^.iid) and IsGUIDEqual(Res^.iid^,iid)) do begin
  543. inc(Res);
  544. dec(i);
  545. end;
  546. if (i>0) then
  547. getinterfaceentry:=Res;
  548. end;
  549. if (getinterfaceentry=nil)and not(classparent=nil) then
  550. getinterfaceentry:=classparent.getinterfaceentry(iid)
  551. end;
  552. class function TObject.getinterfaceentrybystr(const iidstr : string) : pinterfaceentry;
  553. var
  554. i: integer;
  555. intftable: pinterfacetable;
  556. Res: pinterfaceentry;
  557. begin
  558. getinterfaceentrybystr:=nil;
  559. intftable:=getinterfacetable;
  560. if assigned(intftable) then begin
  561. i:=intftable^.EntryCount;
  562. Res:=@intftable^.Entries[0];
  563. while (i>0) and (Res^.iidstr^<>iidstr) do begin
  564. inc(Res);
  565. dec(i);
  566. end;
  567. if (i>0) then
  568. getinterfaceentrybystr:=Res;
  569. end;
  570. if (getinterfaceentrybystr=nil)and not(classparent=nil) then
  571. getinterfaceentrybystr:=classparent.getinterfaceentrybystr(iidstr)
  572. end;
  573. class function TObject.getinterfacetable : pinterfacetable;
  574. begin
  575. getinterfacetable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  576. end;
  577. {****************************************************************************
  578. TINTERFACEDOBJECT
  579. ****************************************************************************}
  580. function TInterfacedObject.QueryInterface(
  581. const iid : tguid;out obj) : longint;stdcall;
  582. begin
  583. if getinterface(iid,obj) then
  584. result:=0
  585. else
  586. result:=longint($80004002);
  587. end;
  588. function TInterfacedObject._AddRef : longint;stdcall;
  589. begin
  590. inclocked(frefcount);
  591. _addref:=frefcount;
  592. end;
  593. function TInterfacedObject._Release : longint;stdcall;
  594. begin
  595. if declocked(frefcount) then
  596. begin
  597. self.destroy;
  598. _Release:=0;
  599. end
  600. else
  601. _Release:=frefcount;
  602. end;
  603. procedure TInterfacedObject.AfterConstruction;
  604. begin
  605. { we need to fix the refcount we forced in newinstance }
  606. { further, it must be done in a thread safe way }
  607. declocked(frefcount);
  608. end;
  609. procedure TInterfacedObject.BeforeDestruction;
  610. begin
  611. if frefcount<>0 then
  612. HandleError(204);
  613. end;
  614. class function TInterfacedObject.NewInstance : TObject;
  615. begin
  616. NewInstance:=inherited NewInstance;
  617. TInterfacedObject(NewInstance).frefcount:=1;
  618. end;
  619. {$endif HASINTF}
  620. {****************************************************************************
  621. Exception Support
  622. ****************************************************************************}
  623. {$i except.inc}
  624. {****************************************************************************
  625. Initialize
  626. ****************************************************************************}
  627. {
  628. $Log$
  629. Revision 1.45 2004-12-05 21:09:54 florian
  630. * fixed memory release in TInterfacedObject._Release
  631. Revision 1.44 2004/11/03 11:33:50 florian
  632. * fixed dyn. array handling for 32 bit architectures requiering proper alignment
  633. Revision 1.42 2004/10/24 20:01:41 peter
  634. * saveregisters calling convention is obsolete
  635. Revision 1.41 2004/10/10 19:18:31 florian
  636. * fixed aligntoptr
  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. }