Skip to content

[Rtti] Invoke (ffi.manager implemention) and records as arguments

Summary

ffi.manager have a few bugs around passing records as arguments for example

program project1;
{$mode delphi}
{$H+} {$M+}
{$RTTI EXPLICIT METHODS([vcPublished]) PROPERTIES([vcPublished]) FIELDS([vcPublished])}
uses
  SysUtils, TypInfo, Rtti, ffi.manager;

type
  TRec2 = record
    P: Pointer;
    Intf: IUnknown;
    B: Byte;
  end;

type

  { TMyObj }

  TMyObj = class
  strict private
    FStr: string;
  public
    constructor Create;
  published
    procedure Test2Const(const ARec: TRec2); //you get garbage in ARec
  end;

var
  ErrorCount: Integer;

procedure Check(ACondition: boolean; const AMessage: string);
begin
  if not ACondition then
  begin
    WriteLn('ERROR: ' + AMessage);
    INc(ErrorCount);
  end;
end;

var
  Intf: IUnknown;

{ TMyObj }

constructor TMyObj.Create;
begin
  FStr := '123';
end;

procedure TMyObj.Test2Const(const ARec: TRec2);
begin
  Check(FStr = '123', 'Test2Const: Self is broken');
  Check(ARec.Intf = Intf, 'Test2Const: ARec is broken');
  Check(ARec.B = 59, 'Test2Const: ARec is broken');
end;

procedure ZeroRecord(var Rec; ATypeInfo: PTypeInfo);
begin
  FinalizeArray(@Rec, ATypeInfo, 1);
  FillChar(Rec, GetTypeData(ATypeInfo).RecSize, 0);
end;

var
  O: TMyObj;
  Context: TRttiContext;
  R2: TRec2;
begin
  O := TMyObj.Create;
  Intf := TInterfacedObject.Create;
  try
  Context := TRttiContext.Create;
  try
    R2.Intf := Intf;
    R2.B := 59;
    Context.GetType(TMyObj).GetMethod('Test2Const').Invoke(O, [TValue.From<TRec2>(R2)]);
  finally
    Context.Free; O.Free;
  end;
  if ErrorCount > 0 then
    Halt(ErrorCount);
  WriteLn('OK');
  except
    on E: Exception do
    begin
      WriteLn(E.ClassName + ': ' + E.Message);
      Halt(1);
    end;
  end;
end.

System Information

  • Operating system: Linux
  • Processor architecture: x86-64
  • Compiler version: trunk

Steps to reproduce

patch and full test be added in next commit

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information