Recent

Author Topic: Getting address of TSomeObject.AfterConstruction without using PVMT  (Read 1380 times)

BrunoK

  • Full Member
  • ***
  • Posts: 190
  • Retired programmer
In the following procedure
Code: Pascal  [Select]
  1. const
  2.   cCPEmptyMethod : Codepointer = nil;
  3.   cCPAfterConstruction : Codepointer = nil;
  4.  
  5. function _InternalCreate(aSelf : TClass; aCreate: UIntPtr): TObject;
  6. var
  7.   lAfterConstruction : CodePointer;
  8. begin
  9.   Result := aSelf.Newinstance;
  10.   if Result = nil then
  11.     exit;
  12.   { TObject.AfterConstruction does nothing, skip try / finally block thus
  13.     reducing code overhead for 90% of classes (?) }
  14.   lAfterConstruction := PVMT(aSelf)^.vAfterConstruction;
  15.   // lAfterConstruction := @Result.AfterConstruction; // if activated, generates error
  16.   // fstobjcr.pp(96,25) Error: Incompatible types: got "<procedure variable type of procedure of object;Register>" expected "Pointer"
  17.   if lAfterConstruction <> cCPAfterConstruction then
  18.     if lAfterConstruction <> cCPEmptyMethod then
  19.      try
  20.        lAfterConstruction := nil;
  21.        Result.AfterConstruction;
  22.        lAfterConstruction := Result;
  23.      finally
  24.        if lAfterConstruction = nil then begin // Failed AfterConstruction
  25.          Result.Destroy;
  26.          Result := nil;
  27.        end;
  28.      end;
  29. end;
  30.  
I would like to replace  PVMT(aSelf)^.vAfterConstruction with something like shown in the next line. But expressed  like in snippet line 15, it gives error like in line 16.
Is there a way to get 'simply' (without having to go through complicated things that I already know how to do) a correct transtyping of lAfterConstruction := @Result.AfterConstruction.
Lazarus trunk r. 62137/27.10.2019 (+/- patches regarding TScrollBar, IntitalSetupDialog, Options.Environment options, SearchResults).  Lazarus 3.0.6 raw from svn.
FPC 3.0.4 32 bits. (+heaptrc with leaked ClassName+Revisited TList) , Windows 10 Pro x64 (v. 1903 / 18362.418)

howardpc

  • Hero Member
  • *****
  • Posts: 3176
Re: Getting address of TSomeObject.AfterConstruction without using PVMT
« Reply #1 on: February 02, 2019, 11:57:39 am »
The following compiles. Whether it achieves what you want, I am not sure.
Code: Pascal  [Select]
  1. uses Forms;
  2.  
  3. function _InternalCreatedOK(aSelf: TClass; out anInstance: TObject): Boolean;
  4. var
  5.   lAfterConstruction: TProcedureOfObject;
  6. begin
  7.   Result := True;
  8.   anInstance := aSelf.newinstance;
  9.   if anInstance = Nil then
  10.     Exit(False);
  11.   lAfterConstruction := @anInstance.AfterConstruction; // if activated, generates error
  12.   try
  13.     if Assigned(lAfterConstruction) then
  14.     lAfterConstruction := Nil;
  15.     anInstance.AfterConstruction;
  16.   finally
  17.     if Assigned(lAfterConstruction) then begin // Failed AfterConstruction
  18.       anInstance.Destroy;
  19.       anInstance := Nil;
  20.       Result := False;
  21.     end;
  22.   end;
  23. end;

ASerge

  • Hero Member
  • *****
  • Posts: 1411
Re: Getting address of TSomeObject.AfterConstruction without using PVMT
« Reply #2 on: February 02, 2019, 12:06:39 pm »
May be this:
Code: Pascal  [Select]
  1. {$MODE OBJFPC}
  2.  
  3. var
  4.   GAfterConstruction: CodePointer = nil;
  5.  
  6. type
  7.   TAfterContruction = procedure of object;
  8.  
  9. function GetCodeOfAfterContruction(Method: TAfterContruction): CodePointer; inline;
  10. begin
  11.   Result := TMethod(Method).Code;
  12. end;
  13.  
  14. function _InternalCreate(ASelf: TClass; aCreate: UIntPtr): TObject;
  15. var
  16.   LAfterConstruction: CodePointer;
  17. begin
  18.   Result := ASelf.NewInstance;
  19.   if Result = nil then
  20.     Exit;
  21. { TObject.AfterConstruction does nothing, skip try / finally block thus
  22.   reducing code overhead for 90% of classes (?) }
  23.   LAfterConstruction := GetCodeOfAfterContruction(@Result.AfterConstruction);
  24.   if LAfterConstruction = GAfterConstruction then
  25.     // Skip default
  26.   else
  27.     Result.AfterConstruction;
  28. end;
  29.  
  30. procedure InitGAfterConstruction;
  31. var
  32.   Dummy: TObject;
  33. begin
  34.   Dummy := TObject.Create;
  35.   try
  36.     GAfterConstruction := GetCodeOfAfterContruction(@Dummy.AfterConstruction);
  37.   finally
  38.     Dummy.Free;
  39.   end;
  40. end;
  41.  
  42. begin
  43.   InitGAfterConstruction;
  44. end.

BrunoK

  • Full Member
  • ***
  • Posts: 190
  • Retired programmer
Re: Getting address of TSomeObject.AfterConstruction without using PVMT
« Reply #3 on: February 02, 2019, 12:49:21 pm »
@howardpc, @ASerge
Thanks. As soon as my 3.0.6 is again functional (some little modifications beiing done), I'll test.
The objective is to have as little byte code as possible, otherwise what I'm trying to do do is useless (once again ...).
Lazarus trunk r. 62137/27.10.2019 (+/- patches regarding TScrollBar, IntitalSetupDialog, Options.Environment options, SearchResults).  Lazarus 3.0.6 raw from svn.
FPC 3.0.4 32 bits. (+heaptrc with leaked ClassName+Revisited TList) , Windows 10 Pro x64 (v. 1903 / 18362.418)