Rtti.Invoke is not working correctly on Linux using ffi.manager
I created a small test for Rtti.Invoke
and it worked successfully on Windows, however, there were problems in the implementation of ffi.manager
.
Test code:
program RttiInvokeTest;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
Classes,
TypInfo,
Rtti
{$ifndef Windows}
, ffi.manager
{$endif};
type
TMyClass=class
public
MyField: integer;
end;
TTestClass=class
public
Info: string;
function TestAll(arg1: TPoint; arg2: TRect; arg3: TMyClass; arg4: Integer; arg5: Pointer; arg6: Double; arg7: Boolean; arg8: string): TPoint;
end;
function TTestClass.TestAll(arg1: TPoint; arg2: TRect; arg3: TMyClass; arg4: Integer; arg5: Pointer; arg6: Double; arg7: Boolean; arg8: string): TPoint;
begin
WriteLn('Self Info: ', Self.Info);
WriteLn('getted Point(', arg1.X, ', ', arg1.Y, ')');
WriteLn('getted Rect(', arg2.Left, ', ', arg2.Top, ', ', arg2.Right, ', ', arg2.Bottom, ')');
WriteLn('my class field: ', arg3.MyField);
WriteLn('integer: ', arg4);
WriteLn('my class (by pointer) field: ', TMyClass(arg5).MyField);
WriteLn('double: ', arg6:0:5);
WriteLn('boolean: ', arg7);
WriteLn('string: ', arg8);
Result := Point(1111, 2222);
end;
var
p, pnt_arg: Pointer;
point, pnt_ret: TPoint;
rect: TRect;
myClass: TMyClass;
int: Integer;
dbl: Double;
bln: Boolean;
str: string;
testClass: TTestClass;
val1, val2, val3, val5, val_self, val_ret: TValue;
begin
p := @TTestClass.TestAll;
point := TPoint.Create(123, 456);
rect := TRect.Create(12, 34, 56, 78);
myClass := TMyClass.Create;
myClass.MyField:=123456;
pnt_arg := Pointer(myClass);
TValue.Make(@point, TypeInfo(TPoint), val1);
TValue.Make(@rect, TypeInfo(TRect), val2);
TValue.Make(@myClass, TypeInfo(TMyClass), val3);
TValue.Make(@pnt_arg, TypeInfo(Pointer), val5);
int := 3456789;
dbl := 9876.54321;
bln := True;
str := 'simple str';
testClass := TTestClass.Create;
testClass.Info:='TestClass Information';
TValue.Make(@testClass, TypeInfo(TTestClass), val_self);
val_ret := Rtti.Invoke(p, [val_self, val1, val2, val3, int, val5, dbl, bln, str], ccReg, TypeInfo(TPoint), False, False);
pnt_ret := TPoint(val_ret.GetReferenceToRawData^);
WriteLn('returned Point(', pnt_ret.X, ', ', pnt_ret.Y, ')');
ReadLn;
end.
Incorrect output on Linux:
Self Info: TestClass Information
getted Point(123, 0)
getted Rect(12, 34, 56, 0)
my class field: 123456
integer: 3456789
my class (by pointer) field: 123456
double: 9876.54321
boolean: TRUE
string: simple str
returned Point(1111, 0)
Output on Windows (x64), consistent with the expected output:
Self Info: TestClass Information
getted Point(123, 456)
getted Rect(12, 34, 56, 78)
my class field: 123456
integer: 3456789
my class (by pointer) field: 123456
double: 9876.54321
boolean: TRUE
string: simple str
returned Point(1111, 2222)