tw16034.pp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. program Hello;
  2. {$ifdef fpc}
  3. {$mode delphi}
  4. {$endif}
  5. {$APPTYPE CONSOLE}
  6. {$O-}
  7. type
  8. ptr = pointer;
  9. {$ifdef fpc}
  10. codeptr = codepointer;
  11. {$else}
  12. codeptr = pointer;
  13. {$endif}
  14. Int = ptrint;
  15. pPtr = ^ptr;
  16. UInt = ptruint;
  17. Bool = Boolean;
  18. // Object woth VMT at offset 0.
  19. TObj0 =
  20. object
  21. Constructor Init;
  22. Function Value(p: UInt): UInt; Virtual;
  23. enD;
  24. // Object with VMT at offset 0, and size = 5.
  25. TObj1 =
  26. object (TObj0)
  27. f1: Byte; // UInt;
  28. Constructor Init;
  29. Function Value(p: UInt): UInt; Virtual;
  30. enD;
  31. // Object with VMT at offset 0, but size = 8. (???)
  32. TObj2 =
  33. object
  34. f1{, f2, f3, f4}: Byte; // UInt;
  35. Constructor Init;
  36. Function Value(p: UInt): UInt; Virtual;
  37. enD;
  38. { Implmentation }
  39. Constructor TObj0.Init;
  40. begin
  41. enD;
  42. Function TObj0.Value(p: UInt): UInt;
  43. begin
  44. Result := 0;
  45. enD;
  46. Constructor TObj1.Init;
  47. begin
  48. enD;
  49. Function TObj1.Value(p: UInt): UInt;
  50. begin
  51. Result := 0;
  52. enD;
  53. Constructor TObj2.Init;
  54. begin
  55. enD;
  56. Function TObj2.Value(p: UInt): UInt;
  57. begin
  58. Result := 0;
  59. enD;
  60. { Low Level VMT Routines }
  61. type
  62. pObjVMT = ^TObjVMT;
  63. ppObjVMT = ^pObjVMT;
  64. TObjVMT =
  65. record
  66. fInstanceSize: UInt;
  67. fInstanceSize2: Int;
  68. fParent: ppObjVMT;
  69. enD;
  70. Function GetInstanceSize(AVMT: pObjVMT): UInt;
  71. begin
  72. Result := AVMT.fInstanceSize;
  73. enD;
  74. Function GetVMTPtrOffset(AVMT: pObjVMT): UInt;
  75. begin
  76. if (AVMT.fParent = nil) then
  77. Result := GetInstanceSize(AVMT) - SizeOf(ptr) else
  78. Result := GetVMTPtrOffset(AVMT.fParent^);
  79. enD;
  80. Function SetVMT(Obj: ptr; AVMT: ptr): Bool;
  81. begin
  82. Result := (AVMT <> nil);
  83. if (Result) then
  84. pPtr(UInt(Obj) + GetVMTPtrOffset(AVMT))^ := AVMT;
  85. enD;
  86. { Main }
  87. var
  88. O0: TObj0;
  89. O1: TObj1;
  90. O2: TObj2;
  91. s0, s1, s2: UInt;
  92. v0, v1, v2: ptr;
  93. cn0, cn1, cn2: codeptr;
  94. begin
  95. // VMT Pointers
  96. v0 := TypeOf(TObj0);
  97. v1 := TypeOf(TObj1);
  98. v2 := TypeOf(TObj2);
  99. // Object sizes
  100. s0 := SizeOf(TObj0); // = 4
  101. s1 := SizeOf(TObj1); // = 5
  102. s2 := SizeOf(TObj2); // = 8 (???)
  103. writeln(s0);
  104. writeln(s1);
  105. writeln(s2);
  106. // Method pointers
  107. cn0 := @TObj0.Value;
  108. cn1 := @TObj1.Value;
  109. cn2 := @TObj2.Value;
  110. // VMT offsets (use in watches - need in program!)
  111. // Int(@o0._vptr$) - Int(@o0) = 0
  112. // Int(@o1._vptr$) - Int(@o1) = 0
  113. // Int(@o2._vptr$) - Int(@o2) = 1 (???)
  114. {
  115. // Constructors - skipping
  116. O0.Init;
  117. O1.Init;
  118. O2.Init;
  119. }
  120. // Store VMT (emulate constructor)
  121. SetVMT(@O0, TypeOf(TObj0));
  122. SetVMT(@O1, TypeOf(TObj1));
  123. SetVMT(@O2, TypeOf(TObj2));
  124. // Call Virtual Functions
  125. O2.f1 := O0.Value(0);
  126. O2.f1 := O1.Value(0);
  127. O2.f1 := O2.Value(0); {CRASHES !!!}
  128. { SizeOf(TObj2) must be 5,
  129. or ptr(Int(@o2._vptr$) - Int(@o2)) must be 4! }
  130. // MessageBox will be displayed, if all was successfull
  131. writeln(O2.f1, 'Hello, FPC uWorld!', 'Hello', 0);
  132. end.