objpas.inc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  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 =
  252. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  253. packed
  254. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  255. record
  256. FieldOffset: PtrUInt;
  257. ClassTypeIndex: Word;
  258. Name: ShortString;
  259. end;
  260. PFieldTable = ^TFieldTable;
  261. TFieldTable =
  262. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  263. packed
  264. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  265. record
  266. FieldCount: Word;
  267. ClassTable: Pointer;
  268. { should be array[Word] of TFieldInfo; but
  269. Elements have variant size! force at least proper alignment }
  270. Fields: array[0..0] of TFieldInfo
  271. end;
  272. var
  273. UName: ShortString;
  274. CurClassType: TClass;
  275. FieldTable: PFieldTable;
  276. FieldInfo: PFieldInfo;
  277. i: Integer;
  278. begin
  279. if Length(name) > 0 then
  280. begin
  281. UName := UpCase(name);
  282. CurClassType := ClassType;
  283. while CurClassType <> nil do
  284. begin
  285. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  286. if FieldTable <> nil then
  287. begin
  288. FieldInfo := @FieldTable^.Fields;
  289. for i := 0 to FieldTable^.FieldCount - 1 do
  290. begin
  291. if UpCase(FieldInfo^.Name) = UName then
  292. begin
  293. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  294. exit;
  295. end;
  296. FieldInfo := @FieldInfo^.Name + 1 + Length(FieldInfo^.Name);
  297. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  298. { align to largest field of TFieldInfo }
  299. FieldInfo := Align(FieldInfo, SizeOf(PtrUInt));
  300. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  301. end;
  302. end;
  303. { Try again with the parent class type }
  304. CurClassType:=pclass(pointer(CurClassType)+vmtParent)^;
  305. end;
  306. end;
  307. fieldaddress:=nil;
  308. end;
  309. function TObject.SafeCallException(exceptobject : tobject;
  310. exceptaddr : pointer) : longint;
  311. begin
  312. safecallexception:=0;
  313. end;
  314. class function TObject.ClassInfo : pointer;
  315. begin
  316. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  317. end;
  318. class function TObject.ClassName : ShortString;
  319. begin
  320. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  321. end;
  322. class function TObject.ClassNameIs(const name : string) : boolean;
  323. begin
  324. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  325. end;
  326. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  327. var
  328. vmt : tclass;
  329. begin
  330. vmt:=self;
  331. while assigned(vmt) do
  332. begin
  333. if vmt=aclass then
  334. begin
  335. InheritsFrom:=true;
  336. exit;
  337. end;
  338. vmt:=pclass(pointer(vmt)+vmtParent)^;
  339. end;
  340. InheritsFrom:=false;
  341. end;
  342. class function TObject.stringmessagetable : pstringmessagetable;
  343. type
  344. pdword = ^dword;
  345. begin
  346. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  347. end;
  348. type
  349. tmessagehandler = procedure(var msg) of object;
  350. tmessagehandlerrec = packed record
  351. proc : pointer;
  352. obj : pointer;
  353. end;
  354. procedure TObject.Dispatch(var message);
  355. type
  356. tmsgtable = packed record
  357. index : dword;
  358. method : pointer;
  359. end;
  360. pmsgtable = ^tmsgtable;
  361. var
  362. index : dword;
  363. count,i : longint;
  364. msgtable : pmsgtable;
  365. p : pointer;
  366. vmt : tclass;
  367. msghandler : tmessagehandler;
  368. begin
  369. index:=dword(message);
  370. vmt:=ClassType;
  371. while assigned(vmt) do
  372. begin
  373. // See if we have messages at all in this class.
  374. p:=pointer(vmt)+vmtDynamicTable;
  375. If Assigned(p) and (Pdword(p)^<>0) then
  376. begin
  377. msgtable:=pmsgtable(PtrInt(p^)+4);
  378. count:=pdword(p^)^;
  379. end
  380. else
  381. Count:=0;
  382. { later, we can implement a binary search here }
  383. for i:=0 to count-1 do
  384. begin
  385. if index=msgtable[i].index then
  386. begin
  387. p:=msgtable[i].method;
  388. tmessagehandlerrec(msghandler).proc:=p;
  389. tmessagehandlerrec(msghandler).obj:=self;
  390. msghandler(message);
  391. exit;
  392. end;
  393. end;
  394. vmt:=pclass(pointer(vmt)+vmtParent)^;
  395. end;
  396. DefaultHandler(message);
  397. end;
  398. procedure TObject.DispatchStr(var message);
  399. type
  400. PSizeUInt = ^SizeUInt;
  401. var
  402. name : shortstring;
  403. count,i : longint;
  404. msgstrtable : pmsgstrtable;
  405. p : pointer;
  406. vmt : tclass;
  407. msghandler : tmessagehandler;
  408. begin
  409. name:=pshortstring(@message)^;
  410. vmt:=ClassType;
  411. while assigned(vmt) do
  412. begin
  413. p:=(pointer(vmt)+vmtMsgStrPtr);
  414. If (P<>Nil) and (PDWord(P)^<>0) then
  415. begin
  416. count:=pdword(PSizeUInt(p)^)^;
  417. msgstrtable:=pmsgstrtable(PSizeUInt(P)^+4);
  418. end
  419. else
  420. Count:=0;
  421. { later, we can implement a binary search here }
  422. for i:=0 to count-1 do
  423. begin
  424. if name=msgstrtable[i].name^ then
  425. begin
  426. p:=msgstrtable[i].method;
  427. tmessagehandlerrec(msghandler).proc:=p;
  428. tmessagehandlerrec(msghandler).obj:=self;
  429. msghandler(message);
  430. exit;
  431. end;
  432. end;
  433. vmt:=pclass(pointer(vmt)+vmtParent)^;
  434. end;
  435. DefaultHandlerStr(message);
  436. end;
  437. procedure TObject.DefaultHandler(var message);
  438. begin
  439. end;
  440. procedure TObject.DefaultHandlerStr(var message);
  441. begin
  442. end;
  443. procedure TObject.CleanupInstance;
  444. Type
  445. TRecElem = packed Record
  446. Info : Pointer;
  447. Offset : Longint;
  448. end;
  449. TRecElemArray = packed array[1..Maxint] of TRecElem;
  450. PRecRec = ^TRecRec;
  451. TRecRec = record
  452. Size,Count : Longint;
  453. Elements : TRecElemArray;
  454. end;
  455. var
  456. vmt : tclass;
  457. temp : pbyte;
  458. count,
  459. i : longint;
  460. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  461. recelem : TRecElem;
  462. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  463. begin
  464. vmt:=ClassType;
  465. while vmt<>nil do
  466. begin
  467. { This need to be included here, because Finalize()
  468. has should support for tkClass }
  469. Temp:=Pointer((Pointer(vmt)+vmtInitTable)^);
  470. if Assigned(Temp) then
  471. begin
  472. inc(Temp);
  473. I:=Temp^;
  474. inc(temp,I+1); // skip name string;
  475. {$ifdef FPC_ALIGNSRTTI}
  476. temp:=aligntoptr(temp);
  477. {$endif FPC_ALIGNSRTTI}
  478. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  479. move(PRecRec(Temp)^.Count,Count,sizeof(Count));
  480. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  481. Count:=PRecRec(Temp)^.Count; // get element Count
  482. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  483. For I:=1 to count do
  484. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  485. begin
  486. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(RecElem));
  487. With RecElem do
  488. int_Finalize (pointer(self)+Offset,Info);
  489. end;
  490. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  491. With PRecRec(Temp)^.elements[I] do
  492. int_Finalize (pointer(self)+Offset,Info);
  493. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  494. end;
  495. vmt:=pclass(pointer(vmt)+vmtParent)^;
  496. end;
  497. end;
  498. procedure TObject.AfterConstruction;
  499. begin
  500. end;
  501. procedure TObject.BeforeDestruction;
  502. begin
  503. end;
  504. {$ifdef HASINTF}
  505. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  506. begin
  507. IsGUIDEqual:=
  508. (guid1.D1=guid2.D1) and
  509. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  510. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  511. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  512. end;
  513. function TObject.getinterface(const iid : tguid;out obj) : boolean;
  514. var
  515. IEntry: pinterfaceentry;
  516. begin
  517. IEntry:=getinterfaceentry(iid);
  518. if Assigned(IEntry) then begin
  519. PPointer(@obj)^:=Pointer(Self)+IEntry^.IOffset;
  520. intf_incr_ref(pointer(obj)); { it must be an com interface }
  521. getinterface:=True;
  522. end
  523. else begin
  524. PPointer(@Obj)^:=nil;
  525. getinterface:=False;
  526. end;
  527. end;
  528. function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
  529. var
  530. IEntry: pinterfaceentry;
  531. begin
  532. IEntry:=getinterfaceentrybystr(iidstr);
  533. if Assigned(IEntry) then begin
  534. PPointer(@obj)^:=Pointer(Self)+IEntry^.IOffset;
  535. if Assigned(IEntry^.iid) then { for Com interfaces }
  536. intf_incr_ref(pointer(obj));
  537. getinterfacebystr:=True;
  538. end
  539. else begin
  540. PPointer(@Obj)^:=nil;
  541. getinterfacebystr:=False;
  542. end;
  543. end;
  544. class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
  545. var
  546. i: integer;
  547. intftable: pinterfacetable;
  548. Res: pinterfaceentry;
  549. begin
  550. getinterfaceentry:=nil;
  551. intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  552. if assigned(intftable) then begin
  553. i:=intftable^.EntryCount;
  554. Res:=@intftable^.Entries[0];
  555. while (i>0) and
  556. not (assigned(Res^.iid) and IsGUIDEqual(Res^.iid^,iid)) do begin
  557. inc(Res);
  558. dec(i);
  559. end;
  560. if (i>0) then
  561. getinterfaceentry:=Res;
  562. end;
  563. if (getinterfaceentry=nil)and not(classparent=nil) then
  564. getinterfaceentry:=classparent.getinterfaceentry(iid)
  565. end;
  566. class function TObject.getinterfaceentrybystr(const iidstr : string) : pinterfaceentry;
  567. var
  568. i: integer;
  569. intftable: pinterfacetable;
  570. Res: pinterfaceentry;
  571. begin
  572. getinterfaceentrybystr:=nil;
  573. intftable:=getinterfacetable;
  574. if assigned(intftable) then begin
  575. i:=intftable^.EntryCount;
  576. Res:=@intftable^.Entries[0];
  577. while (i>0) and (Res^.iidstr^<>iidstr) do begin
  578. inc(Res);
  579. dec(i);
  580. end;
  581. if (i>0) then
  582. getinterfaceentrybystr:=Res;
  583. end;
  584. if (getinterfaceentrybystr=nil)and not(classparent=nil) then
  585. getinterfaceentrybystr:=classparent.getinterfaceentrybystr(iidstr)
  586. end;
  587. class function TObject.getinterfacetable : pinterfacetable;
  588. begin
  589. getinterfacetable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  590. end;
  591. {****************************************************************************
  592. TINTERFACEDOBJECT
  593. ****************************************************************************}
  594. function TInterfacedObject.QueryInterface(
  595. const iid : tguid;out obj) : longint;stdcall;
  596. begin
  597. if getinterface(iid,obj) then
  598. result:=0
  599. else
  600. result:=longint($80004002);
  601. end;
  602. function TInterfacedObject._AddRef : longint;stdcall;
  603. begin
  604. inclocked(frefcount);
  605. _addref:=frefcount;
  606. end;
  607. function TInterfacedObject._Release : longint;stdcall;
  608. begin
  609. if declocked(frefcount) then
  610. begin
  611. self.destroy;
  612. _Release:=0;
  613. end
  614. else
  615. _Release:=frefcount;
  616. end;
  617. procedure TInterfacedObject.AfterConstruction;
  618. begin
  619. { we need to fix the refcount we forced in newinstance }
  620. { further, it must be done in a thread safe way }
  621. declocked(frefcount);
  622. end;
  623. procedure TInterfacedObject.BeforeDestruction;
  624. begin
  625. if frefcount<>0 then
  626. HandleError(204);
  627. end;
  628. class function TInterfacedObject.NewInstance : TObject;
  629. begin
  630. NewInstance:=inherited NewInstance;
  631. TInterfacedObject(NewInstance).frefcount:=1;
  632. end;
  633. {$endif HASINTF}
  634. {****************************************************************************
  635. Exception Support
  636. ****************************************************************************}
  637. {$i except.inc}
  638. {****************************************************************************
  639. Initialize
  640. ****************************************************************************}
  641. {
  642. $Log$
  643. Revision 1.47 2005-03-13 08:34:58 florian
  644. * fixed FieldAddress for 64 bit and CPUs requiring proper alignment
  645. Revision 1.46 2005/02/14 17:13:26 peter
  646. * truncate log
  647. }