tw16034.pp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. TObjVMT =
  64. record
  65. fInstanceSize: UInt;
  66. fInstanceSize2: Int;
  67. fParent: pObjVMT;
  68. enD;
  69. Function GetInstanceSize(AVMT: pObjVMT): UInt;
  70. begin
  71. Result := AVMT.fInstanceSize;
  72. enD;
  73. Function GetVMTPtrOffset(AVMT: pObjVMT): UInt;
  74. begin
  75. if (AVMT.fParent = nil) then
  76. Result := GetInstanceSize(AVMT) - SizeOf(ptr) else
  77. Result := GetVMTPtrOffset(AVMT.fParent);
  78. enD;
  79. Function SetVMT(Obj: ptr; AVMT: ptr): Bool;
  80. begin
  81. Result := (AVMT <> nil);
  82. if (Result) then
  83. pPtr(UInt(Obj) + GetVMTPtrOffset(AVMT))^ := AVMT;
  84. enD;
  85. { Main }
  86. var
  87. O0: TObj0;
  88. O1: TObj1;
  89. O2: TObj2;
  90. s0, s1, s2: UInt;
  91. v0, v1, v2: ptr;
  92. cn0, cn1, cn2: codeptr;
  93. begin
  94. // VMT Pointers
  95. v0 := TypeOf(TObj0);
  96. v1 := TypeOf(TObj1);
  97. v2 := TypeOf(TObj2);
  98. // Object sizes
  99. s0 := SizeOf(TObj0); // = 4
  100. s1 := SizeOf(TObj1); // = 5
  101. s2 := SizeOf(TObj2); // = 8 (???)
  102. writeln(s0);
  103. writeln(s1);
  104. writeln(s2);
  105. // Method pointers
  106. cn0 := @TObj0.Value;
  107. cn1 := @TObj1.Value;
  108. cn2 := @TObj2.Value;
  109. // VMT offsets (use in watches - need in program!)
  110. // Int(@o0._vptr$) - Int(@o0) = 0
  111. // Int(@o1._vptr$) - Int(@o1) = 0
  112. // Int(@o2._vptr$) - Int(@o2) = 1 (???)
  113. {
  114. // Constructors - skipping
  115. O0.Init;
  116. O1.Init;
  117. O2.Init;
  118. }
  119. // Store VMT (emulate constructor)
  120. SetVMT(@O0, TypeOf(TObj0));
  121. SetVMT(@O1, TypeOf(TObj1));
  122. SetVMT(@O2, TypeOf(TObj2));
  123. // Call Virtual Functions
  124. O2.f1 := O0.Value(0);
  125. O2.f1 := O1.Value(0);
  126. O2.f1 := O2.Value(0); {CRASHES !!!}
  127. { SizeOf(TObj2) must be 5,
  128. or ptr(Int(@o2._vptr$) - Int(@o2)) must be 4! }
  129. // MessageBox will be displayed, if all was successfull
  130. writeln(O2.f1, 'Hello, FPC uWorld!', 'Hello', 0);
  131. end.