Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Compiler/Delphi/RTTI    [ Add a report in this area ]  
Report #:  93646   Status: Closed
TRttiMethod fails to invoke method with large record parameter
Project:  Delphi Build #:  15.0.3953.35171
Version:    15.1 Submitted By:   Márton Balassa
Report Type:  Crash / Data loss / Total failure Date Reported:  5/6/2011 8:26:22 AM
Severity:    Critical / Show Stopper Last Updated: 3/20/2012 2:24:39 AM
Platform:    All platforms Internal Tracking #:   283035
Resolution: Fixed (Resolution Comments) Resolved in Build: : 16.0.4160.39594
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: None
Description
When using the Rtti unit to call a method, the method call will fail (with access violation in most cases) if the method has a large (>4 byte) record parameter, the parameter is a const parameter, and the calling convention is stdcall.
Steps to Reproduce:
See the attachment for more details.
-----------
...
type
  ...
  TLargeRecord = record
    A: Cardinal;
    B: Cardinal;
  end;
  IMyInterface = interface(IInvokable)
  ['{75551820-50D2-46D0-A6A9-AED63940664B}']
    procedure TestSmall(const Value: TSmallRecord); stdcall;
    procedure TestMedium(const Value: TMediumRecord); stdcall;
    procedure TestLarge(const Value: TLargeRecord); stdcall;
  end;
  TMyImplementation = class(TInterfacedObject, IMyInterface)
  public
    procedure TestSmall(const Value: TSmallRecord); stdcall;
    procedure TestMedium(const Value: TMediumRecord); stdcall;
    procedure TestLarge(const Value: TLargeRecord); stdcall;
  end;

procedure TMyImplementation.TestLarge(const Value: TLargeRecord);
begin
  WriteLn(Format('Large(%d, %d)', [Value.A, Value.B]));
end;
procedure TMyImplementation.TestMedium(const Value: TMediumRecord);
begin
  WriteLn(Format('Medium(%d, %d)', [Value.A, Value.B]));
end;
procedure TMyImplementation.TestSmall(const Value: TSmallRecord);
begin
  WriteLn(Format('Small(%d, %d)', [Value.A, Value.B]));
end;

procedure TryRtti;
var
  Obj: IMyInterface;
  Ctx: TRttiContext;
  Intf: TRttiInterfaceType;
  Meth: TRttiMethod;
  S: TSmallRecord;
  M: TMediumRecord;
  L: TLargeRecord;
begin
  Obj := TMyImplementation.Create;
  Ctx := TRttiContext.Create;
  try
    Intf := Ctx.GetType(TypeInfo(IMyInterface)) as TRttiInterfaceType;
    ...
    ...
    // large
    L.A := 1;
    L.B := 2;
    Obj.TestLarge(L);
    Intf.GetMethod('TestLarge').Invoke(TValue.From<IMyInterface>(Obj), [TValue.From<TLargeRecord>(L)]);
  finally
    Ctx.Free;
  end;
...
-----------
Workarounds
None, except modifying your classes/interfaces so as they don't have methods like this when the class/interface is to be called with Rtti.
Attachment
RttiStdCallTestCase.zip
Comments

None

Server Response from: ETNACODE01