objpas.inc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. This unit makes Free Pascal as much as possible Delphi compatible
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************
  12. Internal Routines called from the Compiler
  13. ****************************************************************************}
  14. { the reverse order of the parameters make code generation easier }
  15. function fpc_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  16. begin
  17. fpc_do_is:=assigned(aobject) and assigned(aclass) and
  18. aobject.inheritsfrom(aclass);
  19. end;
  20. { the reverse order of the parameters make code generation easier }
  21. function fpc_do_as(aclass : tclass;aobject : tobject): tobject;[public,alias: 'FPC_DO_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  22. begin
  23. if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
  24. handleerrorframe(219,get_frame);
  25. result := aobject;
  26. end;
  27. {$ifndef HASINTF}
  28. { dummies for make cycle with 1.0.x }
  29. procedure fpc_intf_decr_ref(var i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  30. begin
  31. end;
  32. procedure fpc_intf_incr_ref(i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[public,alias: 'FPC_INTF_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  33. begin
  34. end;
  35. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
  36. begin
  37. end;
  38. function fpc_intf_as(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  39. begin
  40. end;
  41. function fpc_class_as_intf(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_CLASS_AS_INTF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  42. begin
  43. end;
  44. {$else HASINTF}
  45. { interface helpers }
  46. procedure fpc_intf_decr_ref(var i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  47. begin
  48. if assigned(i) then
  49. IUnknown(i)._Release;
  50. i:=nil;
  51. end;
  52. {$ifdef hascompilerproc}
  53. { local declaration for intf_decr_ref for local access }
  54. procedure intf_decr_ref(var i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif} [external name 'FPC_INTF_DECR_REF'];
  55. {$endif hascompilerproc}
  56. procedure fpc_intf_incr_ref(i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[public,alias: 'FPC_INTF_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  57. begin
  58. if assigned(i) then
  59. IUnknown(i)._AddRef;
  60. end;
  61. {$ifdef hascompilerproc}
  62. { local declaration of intf_incr_ref for local access }
  63. procedure intf_incr_ref(i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif} [external name 'FPC_INTF_INCR_REF'];
  64. {$endif hascompilerproc}
  65. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
  66. begin
  67. if assigned(S) then
  68. IUnknown(S)._AddRef;
  69. if assigned(D) then
  70. IUnknown(D)._Release;
  71. D:=S;
  72. end;
  73. function fpc_intf_as(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  74. var
  75. tmpi: pointer; // _AddRef before _Release
  76. begin
  77. if assigned(S) then
  78. begin
  79. if IUnknown(S).QueryInterface(iid,tmpi)<>S_OK then
  80. handleerror(219);
  81. fpc_intf_as:=tmpi;
  82. end
  83. else
  84. fpc_intf_as:=nil;
  85. end;
  86. function fpc_class_as_intf(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_CLASS_AS_INTF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  87. var
  88. tmpi: pointer; // _AddRef before _Release
  89. begin
  90. if assigned(S) then
  91. begin
  92. if not TObject(S).GetInterface(iid,tmpi) then
  93. handleerror(219);
  94. fpc_class_as_intf:=tmpi;
  95. end
  96. else
  97. fpc_class_as_intf:=nil;
  98. end;
  99. {$endif HASINTF}
  100. {****************************************************************************
  101. TOBJECT
  102. ****************************************************************************}
  103. constructor TObject.Create;
  104. begin
  105. end;
  106. destructor TObject.Destroy;
  107. begin
  108. end;
  109. procedure TObject.Free;
  110. begin
  111. // the call via self avoids a warning
  112. if self<>nil then
  113. self.destroy;
  114. end;
  115. class function TObject.InstanceSize : LongInt;
  116. begin
  117. InstanceSize:=plongint(pointer(self)+vmtInstanceSize)^;
  118. end;
  119. procedure InitInterfacePointers(objclass: tclass;instance : pointer);
  120. {$ifdef HASINTF}
  121. var
  122. intftable : pinterfacetable;
  123. i : longint;
  124. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  125. IOffset : longint;
  126. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  127. begin
  128. while assigned(objclass) do
  129. begin
  130. intftable:=pinterfacetable((pointer(objclass)+vmtIntfTable)^);
  131. if assigned(intftable) then
  132. for i:=0 to intftable^.EntryCount-1 do
  133. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  134. begin
  135. move(intftable^.Entries[i].IOffset,IOffset,sizeof(longint));
  136. move(pointer(intftable^.Entries[i].VTable),ppointer(@(PChar(instance)[IOffset]))^,sizeof(pointer));
  137. end;
  138. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  139. ppointer(@(PChar(instance)[intftable^.Entries[i].IOffset]))^:=
  140. pointer(intftable^.Entries[i].VTable);
  141. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  142. objclass:=pclass(pointer(objclass)+vmtParent)^;
  143. end;
  144. end;
  145. {$else HASINTF}
  146. begin
  147. end;
  148. {$endif HASINTF}
  149. class function TObject.InitInstance(instance : pointer) : tobject;
  150. begin
  151. { the size is saved at offset 0 }
  152. fillchar(instance^,plongint(pointer(self)+vmtInstanceSize)^,0);
  153. { insert VMT pointer into the new created memory area }
  154. { (in class methods self contains the VMT!) }
  155. ppointer(instance)^:=pointer(self);
  156. {$ifdef HASINTF}
  157. InitInterfacePointers(self,instance);
  158. {$endif HASINTF}
  159. InitInstance:=TObject(Instance);
  160. end;
  161. class function TObject.ClassParent : tclass;
  162. begin
  163. { type of self is class of tobject => it points to the vmt }
  164. { the parent vmt is saved at offset vmtParent }
  165. classparent:=pclass(pointer(self)+vmtParent)^;
  166. end;
  167. class function TObject.NewInstance : tobject;
  168. var
  169. p : pointer;
  170. begin
  171. getmem(p,plongint(pointer(self)+vmtInstanceSize)^);
  172. if p <> nil then
  173. InitInstance(p);
  174. NewInstance:=TObject(p);
  175. end;
  176. procedure TObject.FreeInstance;
  177. begin
  178. CleanupInstance;
  179. FreeMem(Pointer(Self));
  180. end;
  181. class function TObject.ClassType : TClass;
  182. begin
  183. ClassType:=TClass(Pointer(Self))
  184. end;
  185. type
  186. tmethodnamerec = packed record
  187. name : pshortstring;
  188. addr : pointer;
  189. end;
  190. tmethodnametable = packed record
  191. count : dword;
  192. entries : packed array[0..0] of tmethodnamerec;
  193. end;
  194. pmethodnametable = ^tmethodnametable;
  195. class function TObject.MethodAddress(const name : shortstring) : pointer;
  196. var
  197. UName : ShortString;
  198. methodtable : pmethodnametable;
  199. i : dword;
  200. vmt : tclass;
  201. begin
  202. UName := UpCase(name);
  203. vmt:=self;
  204. while assigned(vmt) do
  205. begin
  206. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  207. if assigned(methodtable) then
  208. begin
  209. for i:=0 to methodtable^.count-1 do
  210. if UpCase(methodtable^.entries[i].name^)=UName then
  211. begin
  212. MethodAddress:=methodtable^.entries[i].addr;
  213. exit;
  214. end;
  215. end;
  216. vmt:=pclass(pointer(vmt)+vmtParent)^;
  217. end;
  218. MethodAddress:=nil;
  219. end;
  220. class function TObject.MethodName(address : pointer) : shortstring;
  221. var
  222. methodtable : pmethodnametable;
  223. i : dword;
  224. vmt : tclass;
  225. begin
  226. vmt:=self;
  227. while assigned(vmt) do
  228. begin
  229. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  230. if assigned(methodtable) then
  231. begin
  232. for i:=0 to methodtable^.count-1 do
  233. if methodtable^.entries[i].addr=address then
  234. begin
  235. MethodName:=methodtable^.entries[i].name^;
  236. exit;
  237. end;
  238. end;
  239. vmt:=pclass(pointer(vmt)+vmtParent)^;
  240. end;
  241. MethodName:='';
  242. end;
  243. function TObject.FieldAddress(const name : shortstring) : pointer;
  244. type
  245. PFieldInfo = ^TFieldInfo;
  246. TFieldInfo =
  247. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  248. packed
  249. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  250. record
  251. FieldOffset: PtrUInt;
  252. ClassTypeIndex: Word;
  253. Name: ShortString;
  254. end;
  255. PFieldTable = ^TFieldTable;
  256. TFieldTable =
  257. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  258. packed
  259. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  260. record
  261. FieldCount: Word;
  262. ClassTable: Pointer;
  263. { should be array[Word] of TFieldInfo; but
  264. Elements have variant size! force at least proper alignment }
  265. Fields: array[0..0] of TFieldInfo
  266. end;
  267. var
  268. UName: ShortString;
  269. CurClassType: TClass;
  270. FieldTable: PFieldTable;
  271. FieldInfo: PFieldInfo;
  272. i: Integer;
  273. begin
  274. if Length(name) > 0 then
  275. begin
  276. UName := UpCase(name);
  277. CurClassType := ClassType;
  278. while CurClassType <> nil do
  279. begin
  280. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  281. if FieldTable <> nil then
  282. begin
  283. FieldInfo := @FieldTable^.Fields;
  284. for i := 0 to FieldTable^.FieldCount - 1 do
  285. begin
  286. if UpCase(FieldInfo^.Name) = UName then
  287. begin
  288. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  289. exit;
  290. end;
  291. FieldInfo := @FieldInfo^.Name + 1 + Length(FieldInfo^.Name);
  292. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  293. { align to largest field of TFieldInfo }
  294. FieldInfo := Align(FieldInfo, SizeOf(PtrUInt));
  295. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  296. end;
  297. end;
  298. { Try again with the parent class type }
  299. CurClassType:=pclass(pointer(CurClassType)+vmtParent)^;
  300. end;
  301. end;
  302. fieldaddress:=nil;
  303. end;
  304. function TObject.SafeCallException(exceptobject : tobject;
  305. exceptaddr : pointer) : longint;
  306. begin
  307. safecallexception:=0;
  308. end;
  309. class function TObject.ClassInfo : pointer;
  310. begin
  311. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  312. end;
  313. class function TObject.ClassName : ShortString;
  314. begin
  315. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  316. end;
  317. class function TObject.ClassNameIs(const name : string) : boolean;
  318. begin
  319. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  320. end;
  321. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  322. var
  323. vmt : tclass;
  324. begin
  325. vmt:=self;
  326. while assigned(vmt) do
  327. begin
  328. if vmt=aclass then
  329. begin
  330. InheritsFrom:=true;
  331. exit;
  332. end;
  333. vmt:=pclass(pointer(vmt)+vmtParent)^;
  334. end;
  335. InheritsFrom:=false;
  336. end;
  337. class function TObject.stringmessagetable : pstringmessagetable;
  338. type
  339. pdword = ^dword;
  340. begin
  341. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  342. end;
  343. type
  344. tmessagehandler = procedure(var msg) of object;
  345. tmessagehandlerrec = packed record
  346. proc : pointer;
  347. obj : pointer;
  348. end;
  349. procedure TObject.Dispatch(var message);
  350. type
  351. tmsgtable = packed record
  352. index : dword;
  353. method : pointer;
  354. end;
  355. pmsgtable = ^tmsgtable;
  356. var
  357. index : dword;
  358. count,i : longint;
  359. msgtable : pmsgtable;
  360. p : pointer;
  361. vmt : tclass;
  362. msghandler : tmessagehandler;
  363. begin
  364. index:=dword(message);
  365. vmt:=ClassType;
  366. while assigned(vmt) do
  367. begin
  368. // See if we have messages at all in this class.
  369. p:=pointer(vmt)+vmtDynamicTable;
  370. If Assigned(p) and (Pdword(p)^<>0) then
  371. begin
  372. msgtable:=pmsgtable(PtrInt(p^)+4);
  373. count:=pdword(p^)^;
  374. end
  375. else
  376. Count:=0;
  377. { later, we can implement a binary search here }
  378. for i:=0 to count-1 do
  379. begin
  380. if index=msgtable[i].index then
  381. begin
  382. p:=msgtable[i].method;
  383. tmessagehandlerrec(msghandler).proc:=p;
  384. tmessagehandlerrec(msghandler).obj:=self;
  385. msghandler(message);
  386. exit;
  387. end;
  388. end;
  389. vmt:=pclass(pointer(vmt)+vmtParent)^;
  390. end;
  391. DefaultHandler(message);
  392. end;
  393. procedure TObject.DispatchStr(var message);
  394. type
  395. PSizeUInt = ^SizeUInt;
  396. var
  397. name : shortstring;
  398. count,i : longint;
  399. msgstrtable : pmsgstrtable;
  400. p : pointer;
  401. vmt : tclass;
  402. msghandler : tmessagehandler;
  403. begin
  404. name:=pshortstring(@message)^;
  405. vmt:=ClassType;
  406. while assigned(vmt) do
  407. begin
  408. p:=(pointer(vmt)+vmtMsgStrPtr);
  409. If (P<>Nil) and (PDWord(P)^<>0) then
  410. begin
  411. count:=pdword(PSizeUInt(p)^)^;
  412. msgstrtable:=pmsgstrtable(PSizeUInt(P)^+4);
  413. end
  414. else
  415. Count:=0;
  416. { later, we can implement a binary search here }
  417. for i:=0 to count-1 do
  418. begin
  419. if name=msgstrtable[i].name^ then
  420. begin
  421. p:=msgstrtable[i].method;
  422. tmessagehandlerrec(msghandler).proc:=p;
  423. tmessagehandlerrec(msghandler).obj:=self;
  424. msghandler(message);
  425. exit;
  426. end;
  427. end;
  428. vmt:=pclass(pointer(vmt)+vmtParent)^;
  429. end;
  430. DefaultHandlerStr(message);
  431. end;
  432. procedure TObject.DefaultHandler(var message);
  433. begin
  434. end;
  435. procedure TObject.DefaultHandlerStr(var message);
  436. begin
  437. end;
  438. procedure TObject.CleanupInstance;
  439. Type
  440. TRecElem = packed Record
  441. Info : Pointer;
  442. Offset : Longint;
  443. end;
  444. TRecElemArray = packed array[1..Maxint] of TRecElem;
  445. PRecRec = ^TRecRec;
  446. TRecRec = record
  447. Size,Count : Longint;
  448. Elements : TRecElemArray;
  449. end;
  450. var
  451. vmt : tclass;
  452. temp : pbyte;
  453. count,
  454. i : longint;
  455. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  456. recelem : TRecElem;
  457. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  458. begin
  459. vmt:=ClassType;
  460. while vmt<>nil do
  461. begin
  462. { This need to be included here, because Finalize()
  463. has should support for tkClass }
  464. Temp:=Pointer((Pointer(vmt)+vmtInitTable)^);
  465. if Assigned(Temp) then
  466. begin
  467. inc(Temp);
  468. I:=Temp^;
  469. inc(temp,I+1); // skip name string;
  470. {$ifdef FPC_ALIGNSRTTI}
  471. temp:=aligntoptr(temp);
  472. {$endif FPC_ALIGNSRTTI}
  473. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  474. move(PRecRec(Temp)^.Count,Count,sizeof(Count));
  475. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  476. Count:=PRecRec(Temp)^.Count; // get element Count
  477. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  478. For I:=1 to count do
  479. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  480. begin
  481. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(RecElem));
  482. With RecElem do
  483. int_Finalize (pointer(self)+Offset,Info);
  484. end;
  485. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  486. With PRecRec(Temp)^.elements[I] do
  487. int_Finalize (pointer(self)+Offset,Info);
  488. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  489. end;
  490. vmt:=pclass(pointer(vmt)+vmtParent)^;
  491. end;
  492. end;
  493. procedure TObject.AfterConstruction;
  494. begin
  495. end;
  496. procedure TObject.BeforeDestruction;
  497. begin
  498. end;
  499. {$ifdef HASINTF}
  500. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  501. begin
  502. IsGUIDEqual:=
  503. (guid1.D1=guid2.D1) and
  504. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  505. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  506. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  507. end;
  508. function TObject.getinterface(const iid : tguid;out obj) : boolean;
  509. var
  510. IEntry: pinterfaceentry;
  511. begin
  512. IEntry:=getinterfaceentry(iid);
  513. if Assigned(IEntry) then
  514. begin
  515. Pointer(obj):=Pointer(Self)+IEntry^.IOffset;
  516. if assigned(pointer(obj)) then
  517. iinterface(obj)._AddRef;
  518. getinterface:=True;
  519. end
  520. else
  521. begin
  522. PPointer(@Obj)^:=nil;
  523. getinterface:=False;
  524. end;
  525. end;
  526. function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
  527. var
  528. IEntry: pinterfaceentry;
  529. begin
  530. IEntry:=getinterfaceentrybystr(iidstr);
  531. if Assigned(IEntry) then
  532. begin
  533. Pointer(obj):=Pointer(Self)+IEntry^.IOffset;
  534. if assigned(pointer(obj)) then
  535. iinterface(obj)._AddRef;
  536. getinterfacebystr:=True;
  537. end
  538. else
  539. 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: objpas.inc,v $
  643. Revision 1.50 2005/05/04 08:56:03 michael
  644. + Removed S_OK declarations, they are in objpash.inc
  645. Revision 1.49 2005/04/28 17:58:18 florian
  646. * getinterface fixed
  647. Revision 1.48 2005/04/05 21:05:31 peter
  648. * call initspecialchars if one of the specialchars is configured
  649. for the first time
  650. Revision 1.47 2005/03/13 08:34:58 florian
  651. * fixed FieldAddress for 64 bit and CPUs requiring proper alignment
  652. Revision 1.46 2005/02/14 17:13:26 peter
  653. * truncate log
  654. }