objpas.inc 24 KB

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