system.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. {
  2. This file is part of the Pas2JS run time library.
  3. Copyright (c) 2018 by Mattias Gaertner
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit System;
  11. {$mode objfpc}
  12. {$modeswitch externalclass}
  13. interface
  14. const
  15. LineEnding = #10;
  16. sLineBreak = LineEnding;
  17. MaxSmallint = 32767;
  18. MinSmallint = -32768;
  19. MaxShortInt = 127;
  20. MinShortInt = -128;
  21. MaxByte = $FF;
  22. MaxWord = $FFFF;
  23. MaxLongint = $7fffffff;
  24. MaxCardinal = LongWord($ffffffff);
  25. Maxint = MaxLongint;
  26. IsMultiThread = false;
  27. {*****************************************************************************
  28. Base types
  29. *****************************************************************************}
  30. type
  31. Integer = LongInt;
  32. Cardinal = LongWord;
  33. DWord = LongWord;
  34. SizeInt = NativeInt;
  35. SizeUInt = NativeUInt;
  36. PtrInt = NativeInt;
  37. PtrUInt = NativeUInt;
  38. ValSInt = NativeInt;
  39. ValUInt = NativeUInt;
  40. ValReal = Double;
  41. Real = Double;
  42. Extended = Double;
  43. Int64 = NativeInt unimplemented; // only 53 bits at runtime
  44. UInt64 = NativeUInt unimplemented; // only 52 bits at runtime
  45. QWord = NativeUInt unimplemented; // only 52 bits at runtime
  46. Single = Double unimplemented;
  47. Comp = NativeInt unimplemented;
  48. NativeLargeInt = NativeInt;
  49. NativeLargeUInt = NativeUInt;
  50. UnicodeString = String;
  51. WideString = String;
  52. WideChar = char;
  53. TDynArrayIndex = NativeInt;
  54. TTextLineBreakStyle = (tlbsLF,tlbsCRLF,tlbsCR);
  55. {*****************************************************************************
  56. TObject, TClass, IUnknown, IInterface, TInterfacedObject
  57. *****************************************************************************}
  58. type
  59. TGuid = record
  60. D1: DWord;
  61. D2: word;
  62. D3: word;
  63. D4: array[0..7] of byte;
  64. end;
  65. TGUIDString = string; // ToDo: use type string when supported by compiler
  66. TClass = class of TObject;
  67. { TObject }
  68. TObject = class
  69. private
  70. class var FClassName: String; external name '$classname';
  71. class var FClassParent: TClass; external name '$ancestor';
  72. class var FUnitName: String; external name '$module.$name';
  73. public
  74. constructor Create;
  75. destructor Destroy; virtual;
  76. // Free is using compiler magic.
  77. // Reasons:
  78. // 1. In JS calling obj.Free when obj=nil would crash.
  79. // 2. In JS freeing memory requires to set all references to nil.
  80. // Therefore any obj.free call is replaced by the compiler with some rtl magic.
  81. procedure Free;
  82. class function ClassType: TClass; assembler;
  83. class property ClassName: String read FClassName;
  84. class function ClassNameIs(const Name: string): boolean;
  85. class property ClassParent: TClass read FClassParent;
  86. class function InheritsFrom(aClass: TClass): boolean; assembler;
  87. class property UnitName: String read FUnitName;
  88. procedure AfterConstruction; virtual;
  89. procedure BeforeDestruction; virtual;
  90. function GetInterface(const iid: TGuid; out obj): boolean;
  91. function GetInterface(const iidstr: String; out obj): boolean; inline;
  92. function GetInterfaceByStr(const iidstr: String; out obj): boolean;
  93. function GetInterfaceWeak(const iid: TGuid; out obj): boolean; // equal to GetInterface but the interface returned is not referenced
  94. function Equals(Obj: TObject): boolean; virtual;
  95. function ToString: String; virtual;
  96. end;
  97. const
  98. { IInterface }
  99. S_OK = 0;
  100. S_FALSE = 1;
  101. E_NOINTERFACE = -2147467262; // FPC: longint($80004002)
  102. E_UNEXPECTED = -2147418113; // FPC: longint($8000FFFF)
  103. E_NOTIMPL = -2147467263; // FPC: longint($80004001)
  104. type
  105. {$Interfaces COM}
  106. IUnknown = interface
  107. ['{00000000-0000-0000-C000-000000000046}']
  108. function QueryInterface(const iid: TGuid; out obj): Integer;
  109. function _AddRef: Integer;
  110. function _Release: Integer;
  111. end;
  112. IInterface = IUnknown;
  113. {$M+}
  114. IInvokable = interface(IInterface)
  115. end;
  116. {$M-}
  117. { Enumerator support }
  118. IEnumerator = interface(IInterface)
  119. function GetCurrent: TObject;
  120. function MoveNext: Boolean;
  121. procedure Reset;
  122. property Current: TObject read GetCurrent;
  123. end;
  124. IEnumerable = interface(IInterface)
  125. function GetEnumerator: IEnumerator;
  126. end;
  127. { TInterfacedObject }
  128. TInterfacedObject = class(TObject,IUnknown)
  129. protected
  130. fRefCount: Integer;
  131. { implement methods of IUnknown }
  132. function QueryInterface(const iid: TGuid; out obj): Integer; virtual;
  133. function _AddRef: Integer; virtual;
  134. function _Release: Integer; virtual;
  135. public
  136. procedure BeforeDestruction; override;
  137. property RefCount: Integer read fRefCount;
  138. end;
  139. TInterfacedClass = class of TInterfacedObject;
  140. { TAggregatedObject - sub or satellite object using same interface as controller }
  141. TAggregatedObject = class(TObject)
  142. private
  143. fController: Pointer;
  144. function GetController: IUnknown;
  145. protected
  146. { implement methods of IUnknown }
  147. function QueryInterface(const iid: TGuid; out obj): Integer; virtual;
  148. function _AddRef: Integer; virtual;
  149. function _Release: Integer; virtual;
  150. public
  151. constructor Create(const aController: IUnknown); reintroduce;
  152. property Controller: IUnknown read GetController;
  153. end;
  154. { TContainedObject }
  155. TContainedObject = class(TAggregatedObject,IInterface)
  156. protected
  157. function QueryInterface(const iid: TGuid; out obj): Integer; override;
  158. end;
  159. const
  160. { for safe as operator support }
  161. IObjectInstance: TGuid = '{D91C9AF4-3C93-420F-A303-BF5BA82BFD23}';
  162. function GUIDToString(const GUID: TGUID): string; external name 'rtl.guidrToStr';
  163. {*****************************************************************************
  164. Init / Exit / ExitProc
  165. *****************************************************************************}
  166. var
  167. ExitCode: Integer; external name 'rtl.exitcode';
  168. IsConsole: Boolean = {$IFDEF NodeJS}true{$ELSE}false{$ENDIF};
  169. type
  170. TOnParamCount = function: Longint;
  171. TOnParamStr = function(Index: Longint): String;
  172. var
  173. OnParamCount: TOnParamCount;
  174. OnParamStr: TOnParamStr;
  175. function ParamCount: Longint;
  176. function ParamStr(Index: Longint): String;
  177. {*****************************************************************************
  178. Math
  179. *****************************************************************************}
  180. var // ToDo: make these const
  181. PI: Double; external name 'Math.PI';
  182. MathE: Double; external name 'Math.E'; // Euler's number
  183. MathLN10: Double; external name 'Math.LN10'; // ln(10)
  184. MathLN2: Double; external name 'Math.LN2'; // ln(2)
  185. MathLog10E: Double; external name 'Math.Log10E'; // log10(e)
  186. MathLog2E: Double; external name 'Math.LOG2E'; // log2(e)
  187. MathSQRT1_2: Double; external name 'Math.SQRT1_2'; // sqrt(0.5)
  188. MathSQRT2: Double; external name 'Math.SQRT2'; // sqrt(2)
  189. function Abs(const A: integer): integer; overload; external name 'Math.abs';
  190. function Abs(const A: NativeInt): integer; overload; external name 'Math.abs';
  191. function Abs(const A: Double): Double; overload; external name 'Math.abs';
  192. function ArcTan(const A, B: Double): Double; external name 'Math.atan';
  193. function Cos(const A: Double): Double; external name 'Math.cos';
  194. function Exp(const A: Double): Double; external name 'Math.exp';
  195. function Frac(const A: Double): Double; assembler;
  196. function Ln(const A: Double): Double; external name 'Math.log';
  197. function Odd(const A: Integer): Boolean; assembler;
  198. function Random(const Range: Integer): Integer; overload; assembler;
  199. function Random: Double; overload; external name 'Math.random';
  200. function Round(const A: Double): NativeInt; external name 'Math.round';
  201. function Sin(const A: Double): Double; external name 'Math.sin';
  202. function Sqr(const A: Integer): Integer; assembler; overload;
  203. function Sqr(const A: Double): Double; assembler; overload;
  204. function sqrt(const A: Double): Double; external name 'Math.sqrt';
  205. function Trunc(const A: Double): NativeInt;
  206. {*****************************************************************************
  207. String functions
  208. *****************************************************************************}
  209. const
  210. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
  211. function Int(const A: Double): double;
  212. function Copy(const S: string; Index, Size: Integer): String; assembler; overload;
  213. function Copy(const S: string; Index: Integer): String; assembler; overload;
  214. procedure Delete(var S: String; Index, Size: Integer); assembler; overload;
  215. function Pos(const Search, InString: String): Integer; assembler; overload;
  216. function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
  217. procedure Insert(const Insertion: String; var Target: String; Index: Integer); overload;
  218. function upcase(c : char) : char; assembler;
  219. function HexStr(Val: NativeInt; cnt: byte): string; external name 'rtl.hexStr'; overload;
  220. procedure val(const S: String; out NI : NativeInt; out Code: Integer); overload;
  221. procedure val(const S: String; out SI : ShortInt; out Code: Integer); overload;
  222. procedure val(const S: String; out B : Byte; out Code: Integer); overload;
  223. procedure val(const S: String; out SI : smallint; out Code: Integer); overload;
  224. procedure val(const S: String; out W : word; out Code : Integer); overload;
  225. procedure val(const S: String; out I : integer; out Code : Integer); overload;
  226. procedure val(const S: String; out C : Cardinal; out Code: Integer); overload;
  227. procedure val(const S: String; out d : double; out Code : Integer); overload;
  228. function StringOfChar(c: Char; l: NativeInt): String;
  229. {*****************************************************************************
  230. Other functions
  231. *****************************************************************************}
  232. procedure Write; varargs; // ToDo: should be compiler built-in function
  233. procedure Writeln; varargs; // ToDo: should be compiler built-in function
  234. Type
  235. TConsoleHandler = Procedure (S : JSValue; NewLine : Boolean);
  236. Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
  237. function Assigned(const V: JSValue): boolean; assembler; overload;
  238. function StrictEqual(const A: JSValue; const B): boolean; assembler;
  239. function StrictInequal(const A: JSValue; const B): boolean; assembler;
  240. implementation
  241. // function parseInt(s: String; Radix: NativeInt): NativeInt; external name 'parseInt'; // may result NaN
  242. function isNaN(i: JSValue): boolean; external name 'isNaN'; // may result NaN
  243. // needed by ClassNameIs, the real SameText is in SysUtils
  244. function SameText(const s1, s2: String): Boolean; assembler;
  245. asm
  246. return s1.toLowerCase() == s2.toLowerCase();
  247. end;
  248. function ParamCount: Longint;
  249. begin
  250. if Assigned(OnParamCount) then
  251. Result:=OnParamCount()
  252. else
  253. Result:=0;
  254. end;
  255. function ParamStr(Index: Longint): String;
  256. begin
  257. if Assigned(OnParamStr) then
  258. Result:=OnParamStr(Index)
  259. else if Index=0 then
  260. Result:='js'
  261. else
  262. Result:='';
  263. end;
  264. function Frac(const A: Double): Double; assembler;
  265. asm
  266. return A % 1;
  267. end;
  268. function Odd(const A: Integer): Boolean; assembler;
  269. asm
  270. return A&1 != 0;
  271. end;
  272. function Random(const Range: Integer): Integer; assembler;
  273. asm
  274. return Math.floor(Math.random()*Range);
  275. end;
  276. function Sqr(const A: Integer): Integer; assembler;
  277. asm
  278. return A*A;
  279. end;
  280. function Sqr(const A: Double): Double; assembler;
  281. asm
  282. return A*A;
  283. end;
  284. function Trunc(const A: Double): NativeInt; assembler;
  285. asm
  286. if (!Math.trunc) {
  287. Math.trunc = function(v) {
  288. v = +v;
  289. if (!isFinite(v)) return v;
  290. return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
  291. };
  292. }
  293. $mod.Trunc = Math.trunc;
  294. return Math.trunc(A);
  295. end;
  296. function Copy(const S: string; Index, Size: Integer): String; assembler;
  297. asm
  298. if (Index<1) Index = 1;
  299. return (Size>0) ? S.substring(Index-1,Index+Size-1) : "";
  300. end;
  301. function Copy(const S: string; Index: Integer): String; assembler;
  302. asm
  303. if (Index<1) Index = 1;
  304. return S.substr(Index-1);
  305. end;
  306. procedure Delete(var S: String; Index, Size: Integer);
  307. var
  308. h: String;
  309. begin
  310. if (Index<1) or (Index>length(S)) or (Size<=0) then exit;
  311. h:=S;
  312. S:=copy(h,1,Index-1)+copy(h,Index+Size);
  313. end;
  314. function Pos(const Search, InString: String): Integer; assembler;
  315. asm
  316. return InString.indexOf(Search)+1;
  317. end;
  318. function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
  319. asm
  320. return InString.indexOf(Search,StartAt-1)+1;
  321. end;
  322. procedure Insert(const Insertion: String; var Target: String; Index: Integer);
  323. var
  324. t: String;
  325. begin
  326. if Insertion='' then exit;
  327. t:=Target;
  328. if Index<1 then
  329. Target:=Insertion+t
  330. else if Index>length(t) then
  331. Target:=t+Insertion
  332. else
  333. Target:=copy(t,1,Index-1)+Insertion+copy(t,Index,length(t));
  334. end;
  335. var
  336. WriteBuf: String;
  337. JSArguments: array of JSValue; external name 'arguments';
  338. WriteCallBack : TConsoleHandler;
  339. Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
  340. begin
  341. Result:=WriteCallBack;
  342. WriteCallBack:=H;
  343. end;
  344. procedure Write;
  345. var
  346. i: Integer;
  347. begin
  348. for i:=0 to length(JSArguments)-1 do
  349. if Assigned(WriteCallBack) then
  350. WriteCallBack(JSArguments[i],False)
  351. else
  352. WriteBuf:=WriteBuf+String(JSArguments[i]);
  353. end;
  354. procedure Writeln;
  355. var
  356. i,l: Integer;
  357. s: String;
  358. begin
  359. L:=length(JSArguments)-1;
  360. if Assigned(WriteCallBack) then
  361. begin
  362. for i:=0 to L do
  363. WriteCallBack(JSArguments[i],I=L);
  364. end
  365. else
  366. begin
  367. s:=WriteBuf;
  368. for i:=0 to L do
  369. s:=s+String(JSArguments[i]);
  370. asm
  371. console.log(s);
  372. end;
  373. WriteBuf:='';
  374. end;
  375. end;
  376. function Int(const A: Double): double;
  377. function FTrunc(const A: Double): double; overload; external name 'Math.trunc';
  378. begin
  379. Result:=FTrunc(A);
  380. end;
  381. function Number(S: String): Double; external name 'Number';
  382. procedure val(const S: String; out NI : NativeInt; out Code: Integer);
  383. var
  384. x : double;
  385. begin
  386. Code:=0;
  387. x:=Number(S);
  388. if isNaN(x) or (X<>Int(X)) then
  389. Code:=1
  390. else
  391. NI:=Trunc(x);
  392. end;
  393. procedure val(const S: String; out SI : ShortInt; out Code: Integer);
  394. var
  395. X:Double;
  396. begin
  397. Code:=0;
  398. x:=Number(S);
  399. if isNaN(x) or (X<>Int(X)) then
  400. Code:=1
  401. else if (x<MinShortInt) or (x>MaxShortInt) then
  402. Code:=2
  403. else
  404. SI:=Trunc(x);
  405. end;
  406. procedure val(const S: String; out SI: smallint; out Code: Integer);
  407. var
  408. x: double;
  409. begin
  410. Code:=0;
  411. x:=Number(S);
  412. if isNaN(x) or (X<>Int(X)) then
  413. Code:=1
  414. else if (x<MinSmallint) or (x>MaxSmallint) then
  415. Code:=2
  416. else
  417. SI:=Trunc(x);
  418. end;
  419. procedure val(const S: String; out C: Cardinal; out Code: Integer);
  420. var
  421. x: double;
  422. begin
  423. Code:=0;
  424. x:=Number(S);
  425. if isNaN(x) or (X<>Int(X)) then
  426. Code:=1
  427. else if (x<0) or (x>MaxCardinal) then
  428. Code:=2
  429. else
  430. C:=trunc(x);
  431. end;
  432. procedure val(const S: String; out B: Byte; out Code: Integer);
  433. var
  434. x: double;
  435. begin
  436. Code:=0;
  437. x:=Number(S);
  438. if isNaN(x) or (X<>Int(X)) then
  439. Code:=1
  440. else if (x<0) or (x>MaxByte) then
  441. Code:=2
  442. else
  443. B:=Trunc(x);
  444. end;
  445. procedure val(const S: String; out W: word; out Code: Integer);
  446. var
  447. x: double;
  448. begin
  449. Code:=0;
  450. x:=Number(S);
  451. if isNaN(x) then
  452. Code:=1
  453. else if (x<0) or (x>MaxWord) then
  454. Code:=2
  455. else
  456. W:=Trunc(x);
  457. end;
  458. procedure val(const S : String; out I : integer; out Code : Integer);
  459. var
  460. x: double;
  461. begin
  462. Code:=0;
  463. x:=Number(S);
  464. if isNaN(x) then
  465. Code:=1
  466. else if x>MaxInt then
  467. Code:=2
  468. else
  469. I:=Trunc(x);
  470. end;
  471. procedure val(const S : String; out d : double; out Code : Integer);
  472. Var
  473. x: double;
  474. begin
  475. x:=Number(S);
  476. if isNaN(x) then
  477. Code:=1
  478. else
  479. begin
  480. Code:=0;
  481. d:=x;
  482. end;
  483. end;
  484. function upcase(c : char) : char; assembler;
  485. asm
  486. return c.toUpperCase();
  487. end;
  488. function StringOfChar(c: Char; l: NativeInt): String;
  489. var
  490. i: Integer;
  491. begin
  492. Result:='';
  493. for i:=1 to l do Result:=Result+c;
  494. end;
  495. function Assigned(const V: JSValue): boolean; assembler;
  496. asm
  497. return (V!=undefined) && (V!=null) && (!rtl.isArray(V) || (V.length > 0));
  498. end;
  499. function StrictEqual(const A: JSValue; const B): boolean; assembler;
  500. asm
  501. return A === B;
  502. end;
  503. function StrictInequal(const A: JSValue; const B): boolean; assembler;
  504. asm
  505. return A !== B;
  506. end;
  507. { TContainedObject }
  508. function TContainedObject.QueryInterface(const iid: TGuid; out obj): Integer;
  509. begin
  510. if GetInterface(iid,obj) then
  511. Result:=S_OK
  512. else
  513. Result:=Integer(E_NOINTERFACE);
  514. end;
  515. { TAggregatedObject }
  516. function TAggregatedObject.GetController: IUnknown;
  517. begin
  518. Result := IUnknown(fController);
  519. end;
  520. function TAggregatedObject.QueryInterface(const iid: TGuid; out obj): Integer;
  521. begin
  522. Result := IUnknown(fController).QueryInterface(iid, obj);
  523. end;
  524. function TAggregatedObject._AddRef: Integer;
  525. begin
  526. Result := IUnknown(fController)._AddRef;
  527. end;
  528. function TAggregatedObject._Release: Integer;
  529. begin
  530. Result := IUnknown(fController)._Release;
  531. end;
  532. constructor TAggregatedObject.Create(const aController: IUnknown);
  533. begin
  534. inherited Create;
  535. { do not keep a counted reference to the controller! }
  536. fController := Pointer(aController);
  537. end;
  538. { TInterfacedObject }
  539. function TInterfacedObject.QueryInterface(const iid: TGuid; out obj): Integer;
  540. begin
  541. if GetInterface(iid,obj) then
  542. Result:=S_OK
  543. else
  544. Result:=Integer(E_NOINTERFACE);
  545. end;
  546. function TInterfacedObject._AddRef: Integer;
  547. begin
  548. inc(fRefCount);
  549. Result:=fRefCount;
  550. end;
  551. function TInterfacedObject._Release: Integer;
  552. begin
  553. dec(fRefCount);
  554. Result:=fRefCount;
  555. if fRefCount=0 then
  556. Destroy;
  557. end;
  558. procedure TInterfacedObject.BeforeDestruction;
  559. begin
  560. if fRefCount<>0 then
  561. asm
  562. rtl.raiseE('EHeapMemoryError');
  563. end;
  564. end;
  565. { TObject }
  566. constructor TObject.Create;
  567. begin
  568. end;
  569. destructor TObject.Destroy;
  570. begin
  571. end;
  572. procedure TObject.Free;
  573. begin
  574. Destroy;
  575. end;
  576. class function TObject.ClassType: TClass; assembler;
  577. asm
  578. return this;
  579. end;
  580. class function TObject.ClassNameIs(const Name: string): boolean;
  581. begin
  582. Result:=SameText(Name,ClassName);
  583. end;
  584. class function TObject.InheritsFrom(aClass: TClass): boolean; assembler;
  585. asm
  586. return (aClass!=null) && ((this==aClass) || aClass.isPrototypeOf(this));
  587. end;
  588. procedure TObject.AfterConstruction;
  589. begin
  590. end;
  591. procedure TObject.BeforeDestruction;
  592. begin
  593. end;
  594. function TObject.GetInterface(const iid: TGuid; out obj): boolean;
  595. begin
  596. asm
  597. var i = iid.$intf;
  598. if (i){
  599. i = rtl.getIntfG(this,i.$guid,2);
  600. if (i){
  601. obj.set(i);
  602. return true;
  603. }
  604. }
  605. end;
  606. Result := GetInterfaceByStr(GUIDToString(iid),obj);
  607. end;
  608. function TObject.GetInterface(const iidstr: String; out obj): boolean;
  609. begin
  610. Result := GetInterfaceByStr(iidstr,obj);
  611. end;
  612. function TObject.GetInterfaceByStr(const iidstr: String; out obj): boolean;
  613. begin
  614. if (iidstr = IObjectInstance) then
  615. begin
  616. obj:=Self;
  617. exit(true);
  618. end;
  619. asm
  620. var i = rtl.getIntfG(this,iidstr,2);
  621. obj.set(i);
  622. return i!==null;
  623. end;
  624. Result:=false;
  625. end;
  626. function TObject.GetInterfaceWeak(const iid: TGuid; out obj): boolean;
  627. begin
  628. Result:=GetInterface(iid,obj);
  629. asm
  630. if (Result){
  631. var o = obj.get();
  632. if (o.$kind==='com'){
  633. o._Release();
  634. }
  635. }
  636. end;
  637. end;
  638. function TObject.Equals(Obj: TObject): boolean;
  639. begin
  640. Result:=Obj=Self;
  641. end;
  642. function TObject.ToString: String;
  643. begin
  644. Result:=ClassName;
  645. end;
  646. initialization
  647. ExitCode:=0; // set it here, so that WPO does not remove it
  648. end.