system.pas 19 KB

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