Search code examples
delphiclass-helpersdelphi-10.1-berlin

How to access a private field from a class helper in Delphi 10.1 Berlin?


I would like to use Gabriel Corneanu's jpegex, a class helper for jpeg.TJPEGImage. Reading this and this I've learned that beyond Delphi Seattle you cannot access private fields anymore like jpegex does (FData in the example below). Poking around with the VMT like David Heffernan proposed is far beyond me. Is there any easier way to get this done?

   type
  // helper to access TJPEGData fields
  TJPEGDataHelper = class helper for TJPEGData
    function  Data: TCustomMemoryStream; inline;
    procedure SetData(D: TCustomMemoryStream);
    procedure SetSize(W,H: integer);
  end;

// TJPEGDataHelper
function TJPEGDataHelper.Data: TCustomMemoryStream;
begin
  Result := self.FData;
end;

Solution

  • Beware! This is a nasty hack and can fail when the internal field structure of the hacked class changes.

    type
      TJPEGDataHack = class(TSharedImage)
        FData: TCustomMemoryStream; // must be at the same relative location as in TJPEGData!
      end;
    
      // TJPEGDataHelper
    function TJPEGDataHelper.Data: TCustomMemoryStream;
    begin
      Result := TJPEGDataHack(self).FData;
    end;
    

    This will only work if the parent class of the "hack" class is the same as the parent class of the original class. So, in this case, TJPEGData inherits from TSharedImage and so does the "hack" class. The positions also need to match up so if there was a field before FData in the list then an equivalent field should sit in the "hack" class, even if it's not used.

    A full description of how it works can be found here:

    Hack #5: Access to private fields