Can I modify a constant in the RTL class System.Classes.TStream and rebuild it at runtime in Delphi XE6?

前端 未结 2 1588
抹茶落季
抹茶落季 2020-12-10 04:14

I am trying to work around a known ugly performance limitation in System.Classes.pas, which has a 1980s era constant buffer limit ($F000) that looks like this:



        
2条回答
  •  醉梦人生
    2020-12-10 04:35

    You can overcome this limitation using a detour, try this sample which uses the Delphi Detours Library

    First define the signature of the method to hook

    var
     Trampoline_TStreamCopyFrom : function (Self : TStream;const Source: TStream; Count: Int64): Int64 = nil;
    

    then implement the detour

    function Detour_TStreamCopyFrom(Self : TStream;const Source: TStream; Count: Int64): Int64;
    const
      MaxBufSize = 1024*1024; //use 1 mb now :)
    var
      BufSize, N: Integer;
      Buffer: TBytes;
    begin
      if Count <= 0 then
      begin
        Source.Position := 0;
        Count := Source.Size;
      end;
      Result := Count;
      if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count;
      SetLength(Buffer, BufSize);
      try
        while Count <> 0 do
        begin
          if Count > BufSize then N := BufSize else N := Count;
          Source.ReadBuffer(Buffer, N);
          Self.WriteBuffer(Buffer, N);
          Dec(Count, N);
        end;
      finally
        SetLength(Buffer, 0);
      end;
    end;
    

    Finally replace the original function by the trampoline (you can use this code in the initialization part of some unit)

      Trampoline_TStreamCopyFrom     := InterceptCreate(@TStream.CopyFrom,   @Detour_TStreamCopyFrom);
    

    And to release the hook you can use

     if Assigned(Trampoline_TStreamCopyFrom) then
       InterceptRemove(@Trampoline_TStreamCopyFrom);
    

提交回复
热议问题