--- Merging r39878 into '.':

U    packages/rtl-objpas/src/inc/rtti.pp
--- Recording mergeinfo for merge of r39878 into '.':
 U   .
--- Recording mergeinfo for merge of r39878 into 'packages/rtl-objpas/src/inc/rtti.pp':
 U   packages/rtl-objpas/src/inc/rtti.pp
--- Merging r39879 into '.':
G    packages/rtl-objpas/src/inc/rtti.pp
--- Recording mergeinfo for merge of r39879 into '.':
 G   .
--- Recording mergeinfo for merge of r39879 into 'packages/rtl-objpas/src/inc/rtti.pp':
 G   packages/rtl-objpas/src/inc/rtti.pp
--- Merging r39880 into '.':
U    packages/libffi/src/ffi.manager.pp
--- Recording mergeinfo for merge of r39880 into '.':
 G   .
--- Recording mergeinfo for merge of r39880 into 'packages/rtl-objpas/src/inc/rtti.pp':
 G   packages/rtl-objpas/src/inc/rtti.pp
--- Merging r39881 into '.':
G    packages/rtl-objpas/src/inc/rtti.pp
G    packages/libffi/src/ffi.manager.pp
--- Recording mergeinfo for merge of r39881 into '.':
 G   .
--- Recording mergeinfo for merge of r39881 into 'packages/rtl-objpas/src/inc/rtti.pp':
 G   packages/rtl-objpas/src/inc/rtti.pp
--- Merging r39883 into '.':
U    packages/rtl-objpas/tests/tests.rtti.pas
--- Recording mergeinfo for merge of r39883 into '.':
 G   .
--- Recording mergeinfo for merge of r39883 into 'packages/rtl-objpas/src/inc/rtti.pp':
 G   packages/rtl-objpas/src/inc/rtti.pp
--- Recording mergeinfo for merge of r39883 into 'packages/rtl-objpas/tests/tests.rtti.pas':
 U   packages/rtl-objpas/tests/tests.rtti.pas
--- Merging r39884 into '.':
G    packages/rtl-objpas/src/inc/rtti.pp
--- Recording mergeinfo for merge of r39884 into '.':
 G   .
--- Recording mergeinfo for merge of r39884 into 'packages/rtl-objpas/src/inc/rtti.pp':
 G   packages/rtl-objpas/src/inc/rtti.pp
--- Recording mergeinfo for merge of r39884 into 'packages/rtl-objpas/tests/tests.rtti.pas':
 G   packages/rtl-objpas/tests/tests.rtti.pas

# revisions: 39878,39879,39880,39881,39883,39884

git-svn-id: branches/fixes_3_2@40287 -
This commit is contained in:
marco 2018-11-12 08:57:15 +00:00
parent f42dffb36d
commit 6f88dbd9d5
3 changed files with 132 additions and 38 deletions

View File

@ -157,6 +157,7 @@ function TypeInfoToFFIType(aTypeInfo: PTypeInfo): pffi_type;
function TypeKindName: String; function TypeKindName: String;
begin begin
Result := '';
WriteStr(Result, aTypeInfo^.Kind); WriteStr(Result, aTypeInfo^.Kind);
end; end;
@ -262,7 +263,7 @@ begin
end; end;
end; end;
function ValueToFFIValue(constref Value: TValue; var aIndirect: Pointer; aIsResult: Boolean): Pointer; function ValueToFFIValue(constref aValue: Pointer; aKind: TTypeKind; aIsResult: Boolean): Pointer;
const const
ResultTypeNeedsIndirection = [ ResultTypeNeedsIndirection = [
tkAString, tkAString,
@ -272,17 +273,85 @@ const
tkDynArray tkDynArray
]; ];
begin begin
aIndirect := Nil; Result := aValue;
Result := Value.GetReferenceToRawData; if (aKind = tkSString) or (aIsResult and (aKind in ResultTypeNeedsIndirection)) then
if (Value.Kind = tkSString) or (aIsResult and (Value.Kind in ResultTypeNeedsIndirection)) then begin Result := @aValue;
aIndirect := Result;
Result := @aIndirect;
end;
end; end;
function FFIValueToValue(Value: Pointer; TypeInfo: PTypeInfo): TValue; procedure FFIValueToValue(Source, Dest: Pointer; TypeInfo: PTypeInfo);
var
size: SizeInt;
td: PTypeData;
begin begin
TValue.Make(Value, TypeInfo, Result); td := GetTypeData(TypeInfo);
size := 0;
case TypeInfo^.Kind of
tkChar,
tkWChar,
tkUChar,
tkEnumeration,
tkBool,
tkInteger,
tkInt64,
tkQWord:
case td^.OrdType of
otSByte,
otUByte:
size := 1;
otSWord,
otUWord:
size := 2;
otSLong,
otULong:
size := 4;
otSQWord,
otUQWord:
size := 8;
end;
tkSet:
size := td^.SetSize;
tkFloat:
case td^.FloatType of
ftSingle:
size := SizeOf(Single);
ftDouble:
size := SizeOf(Double);
ftExtended:
size := SizeOf(Extended);
ftComp:
size := SizeOf(Comp);
ftCurr:
size := SizeOf(Currency);
end;
tkMethod:
size := SizeOf(TMethod);
tkSString:
size := td^.MaxLength + 1;
tkDynArray,
tkLString,
tkAString,
tkUString,
tkWString,
tkClass,
tkPointer,
tkClassRef,
tkInterfaceRaw:
size := SizeOf(Pointer);
tkVariant:
size := SizeOf(tvardata);
tkArray:
size := td^.ArrayData.Size;
tkRecord:
size := td^.RecSize;
tkProcVar:
size := SizeOf(CodePointer);
tkObject: ;
tkHelper: ;
tkFile: ;
end;
if size > 0 then
Move(Source^, Dest^, size);
end; end;
{ move this to type info? } { move this to type info? }
@ -303,7 +372,7 @@ begin
end; end;
procedure FFIInvoke(aCodeAddress: Pointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv; procedure FFIInvoke(aCodeAddress: Pointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv;
aResultType: PTypeInfo; out aResultValue: TValue; aFlags: TFunctionCallFlags); aResultType: PTypeInfo; aResultValue: Pointer; aFlags: TFunctionCallFlags);
function CallConvName: String; inline; function CallConvName: String; inline;
begin begin
@ -314,14 +383,14 @@ var
abi: ffi_abi; abi: ffi_abi;
argtypes: array of pffi_type; argtypes: array of pffi_type;
argvalues: array of Pointer; argvalues: array of Pointer;
argindirect: array of Pointer;
rtype: pffi_type; rtype: pffi_type;
rvalue: ffi_arg; rvalue: ffi_arg;
i, arglen, argoffset, retidx, argstart: LongInt; i, arglen, argoffset, retidx, argstart: LongInt;
cif: ffi_cif; cif: ffi_cif;
retparam: Boolean; retparam: Boolean;
begin begin
aResultValue := TValue.Empty; if Assigned(aResultType) and not Assigned(aResultValue) then
raise EInvocationError.Create(SErrInvokeResultTypeNoValue);
if not (fcfStatic in aFlags) and (Length(aArgs) = 0) then if not (fcfStatic in aFlags) and (Length(aArgs) = 0) then
raise EInvocationError.Create(SErrMissingSelfParam); raise EInvocationError.Create(SErrMissingSelfParam);
@ -371,13 +440,12 @@ begin
SetLength(argtypes, arglen); SetLength(argtypes, arglen);
SetLength(argvalues, arglen); SetLength(argvalues, arglen);
SetLength(argindirect, arglen);
{ the order is Self/Vmt (if any), Result param (if any), other params } { the order is Self/Vmt (if any), Result param (if any), other params }
if not (fcfStatic in aFlags) and retparam then begin if not (fcfStatic in aFlags) and retparam then begin
argtypes[0] := TypeInfoToFFIType(aArgs[0].Value.TypeInfo); argtypes[0] := TypeInfoToFFIType(aArgs[0].Info.ParamType);
argvalues[0] := ValueToFFIValue(aArgs[0].Value, argindirect[0], False); argvalues[0] := ValueToFFIValue(aArgs[0].ValueRef, aArgs[0].Info.ParamType^.Kind, False);
if retparam then if retparam then
Inc(retidx); Inc(retidx);
argstart := 1; argstart := 1;
@ -385,14 +453,13 @@ begin
argstart := 0; argstart := 0;
for i := Low(aArgs) + argstart to High(aArgs) do begin for i := Low(aArgs) + argstart to High(aArgs) do begin
argtypes[i - Low(aArgs) + Low(argtypes) + argoffset] := TypeInfoToFFIType(aArgs[i].Value.TypeInfo); argtypes[i - Low(aArgs) + Low(argtypes) + argoffset] := TypeInfoToFFIType(aArgs[i].Info.ParamType);
argvalues[i - Low(aArgs) + Low(argtypes) + argoffset] := ValueToFFIValue(aArgs[i].Value, argindirect[i + argoffset], False); argvalues[i - Low(aArgs) + Low(argtypes) + argoffset] := ValueToFFIValue(aArgs[i].ValueRef, aArgs[i].Info.ParamType^.Kind, False);
end; end;
if retparam then begin if retparam then begin
argtypes[retidx] := TypeInfoToFFIType(aResultType); argtypes[retidx] := TypeInfoToFFIType(aResultType);
TValue.Make(Nil, aResultType, aResultValue); argvalues[retidx] := ValueToFFIValue(aResultValue, aResultType^.Kind, True);
argvalues[retidx] := ValueToFFIValue(aResultValue, argindirect[retidx], True);
rtype := @ffi_type_void; rtype := @ffi_type_void;
end else begin end else begin
rtype := TypeInfoToFFIType(aResultType); rtype := TypeInfoToFFIType(aResultType);
@ -404,7 +471,7 @@ begin
ffi_call(@cif, ffi_fn(aCodeAddress), @rvalue, @argvalues[0]); ffi_call(@cif, ffi_fn(aCodeAddress), @rvalue, @argvalues[0]);
if Assigned(aResultType) and not retparam then if Assigned(aResultType) and not retparam then
aResultValue := FFIValueToValue(@rvalue, aResultType); FFIValueToValue(@rvalue, aResultValue, aResultType);
end; end;
const const

View File

@ -193,10 +193,11 @@ type
function GetTypeSize: integer; virtual; function GetTypeSize: integer; virtual;
function GetBaseType: TRttiType; virtual; function GetBaseType: TRttiType; virtual;
public public
constructor create(ATypeInfo : PTypeInfo); constructor Create(ATypeInfo : PTypeInfo);
function GetProperties: specialize TArray<TRttiProperty>; virtual; function GetProperties: specialize TArray<TRttiProperty>; virtual;
function GetProperty(const AName: string): TRttiProperty; virtual; function GetProperty(const AName: string): TRttiProperty; virtual;
function GetMethods: specialize TArray<TRttiMethod>; virtual; function GetMethods: specialize TArray<TRttiMethod>; virtual;
function GetMethod(const aName: String): TRttiMethod; virtual;
function GetDeclaredMethods: specialize TArray<TRttiMethod>; virtual; function GetDeclaredMethods: specialize TArray<TRttiMethod>; virtual;
property IsInstance: boolean read GetIsInstance; property IsInstance: boolean read GetIsInstance;
property isManaged: boolean read GetIsManaged; property isManaged: boolean read GetIsManaged;
@ -247,7 +248,7 @@ type
protected protected
function GetVisibility: TMemberVisibility; virtual; function GetVisibility: TMemberVisibility; virtual;
public public
constructor create(AParent: TRttiType); constructor Create(AParent: TRttiType);
property Visibility: TMemberVisibility read GetVisibility; property Visibility: TMemberVisibility read GetVisibility;
property Parent: TRttiType read FParent; property Parent: TRttiType read FParent;
end; end;
@ -265,7 +266,7 @@ type
function GetName: string; override; function GetName: string; override;
function GetHandle: Pointer; override; function GetHandle: Pointer; override;
public public
constructor create(AParent: TRttiType; APropInfo: PPropInfo); constructor Create(AParent: TRttiType; APropInfo: PPropInfo);
function GetValue(Instance: pointer): TValue; function GetValue(Instance: pointer): TValue;
procedure SetValue(Instance: pointer; const AValue: TValue); procedure SetValue(Instance: pointer; const AValue: TValue);
property PropertyType: TRttiType read GetPropertyType; property PropertyType: TRttiType read GetPropertyType;
@ -381,11 +382,16 @@ type
EInvocationError = class(Exception); EInvocationError = class(Exception);
ENonPublicType = class(Exception); ENonPublicType = class(Exception);
TFunctionCallParameter = record TFunctionCallParameterInfo = record
Value: TValue; ParamType: PTypeInfo;
ParamFlags: TParamFlags; ParamFlags: TParamFlags;
ParaLocs: PParameterLocations; ParaLocs: PParameterLocations;
end; end;
TFunctionCallParameter = record
ValueRef: Pointer;
Info: TFunctionCallParameterInfo;
end;
TFunctionCallParameterArray = specialize TArray<TFunctionCallParameter>; TFunctionCallParameterArray = specialize TArray<TFunctionCallParameter>;
TFunctionCallFlag = ( TFunctionCallFlag = (
@ -400,7 +406,7 @@ type
TFunctionCallManager = record TFunctionCallManager = record
Invoke: procedure(CodeAddress: CodePointer; const Args: TFunctionCallParameterArray; CallingConvention: TCallConv; Invoke: procedure(CodeAddress: CodePointer; const Args: TFunctionCallParameterArray; CallingConvention: TCallConv;
ResultType: PTypeInfo; out ResultValue: TValue; Flags: TFunctionCallFlags); ResultType: PTypeInfo; ResultValue: Pointer; Flags: TFunctionCallFlags);
CreateCallbackProc: function(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback; CreateCallbackProc: function(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
CreateCallbackMethod: function(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback; CreateCallbackMethod: function(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
FreeCallback: procedure(aCallback: TFunctionCallCallback; aCallConv: TCallConv); FreeCallback: procedure(aCallback: TFunctionCallCallback; aCallConv: TCallConv);
@ -433,6 +439,7 @@ function IsManaged(TypeInfo: PTypeInfo): boolean;
{ these resource strings are needed by units implementing function call managers } { these resource strings are needed by units implementing function call managers }
resourcestring resourcestring
SErrInvokeNotImplemented = 'Invoke functionality is not implemented'; SErrInvokeNotImplemented = 'Invoke functionality is not implemented';
SErrInvokeResultTypeNoValue = 'Function has a result type, but no result pointer provided';
SErrInvokeFailed = 'Invoke call failed'; SErrInvokeFailed = 'Invoke call failed';
SErrCallbackNotImplented = 'Callback functionality is not implemented'; SErrCallbackNotImplented = 'Callback functionality is not implemented';
SErrCallConvNotSupported = 'Calling convention not supported: %s'; SErrCallConvNotSupported = 'Calling convention not supported: %s';
@ -573,7 +580,7 @@ var
FuncCallMgr: TFunctionCallManagerArray; FuncCallMgr: TFunctionCallManagerArray;
procedure NoInvoke(aCodeAddress: CodePointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv; procedure NoInvoke(aCodeAddress: CodePointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv;
aResultType: PTypeInfo; out aResultValue: TValue; aFlags: TFunctionCallFlags); aResultType: PTypeInfo; aResultValue: Pointer; aFlags: TFunctionCallFlags);
begin begin
raise ENotImplemented.Create(SErrInvokeNotImplemented); raise ENotImplemented.Create(SErrInvokeNotImplemented);
end; end;
@ -722,12 +729,18 @@ begin
SetLength(funcargs, Length(aArgs)); SetLength(funcargs, Length(aArgs));
for i := Low(aArgs) to High(aArgs) do begin for i := Low(aArgs) to High(aArgs) do begin
funcargs[i - Low(aArgs) + Low(funcargs)].Value := aArgs[i]; funcargs[i - Low(aArgs) + Low(funcargs)].ValueRef := aArgs[i].GetReferenceToRawData;
funcargs[i - Low(aArgs) + Low(funcargs)].ParamFlags := []; funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamType := aArgs[i].TypeInfo;
funcargs[i - Low(aArgs) + Low(funcargs)].ParaLocs := Nil; funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamFlags := [];
funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParaLocs := Nil;
end; end;
FuncCallMgr[aCallConv].Invoke(aCodeAddress, funcargs, aCallConv, aResultType, Result, flags); if Assigned(aResultType) then
TValue.Make(Nil, aResultType, Result)
else
Result := TValue.Empty;
FuncCallMgr[aCallConv].Invoke(aCodeAddress, funcargs, aCallConv, aResultType, Result.GetReferenceToRawData, flags);
end; end;
function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback; function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of PTypeInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
@ -1855,7 +1868,7 @@ end;
function TValue.GetReferenceToRawData: Pointer; function TValue.GetReferenceToRawData: Pointer;
begin begin
if IsEmpty then if not Assigned(FData.FTypeInfo) then
Result := Nil Result := Nil
else if Assigned(FData.FValueData) then else if Assigned(FData.FValueData) then
Result := FData.FValueData.GetReferenceToRawData Result := FData.FValueData.GetReferenceToRawData
@ -2299,9 +2312,9 @@ begin
result := mvPublished; result := mvPublished;
end; end;
constructor TRttiMember.create(AParent: TRttiType); constructor TRttiMember.Create(AParent: TRttiType);
begin begin
inherited create(); inherited Create();
FParent := AParent; FParent := AParent;
end; end;
@ -2338,9 +2351,9 @@ begin
Result := FPropInfo; Result := FPropInfo;
end; end;
constructor TRttiProperty.create(AParent: TRttiType; APropInfo: PPropInfo); constructor TRttiProperty.Create(AParent: TRttiType; APropInfo: PPropInfo);
begin begin
inherited create(AParent); inherited Create(AParent);
FPropInfo := APropInfo; FPropInfo := APropInfo;
end; end;
@ -2548,9 +2561,9 @@ begin
Result := FTypeInfo; Result := FTypeInfo;
end; end;
constructor TRttiType.create(ATypeInfo: PTypeInfo); constructor TRttiType.Create(ATypeInfo: PTypeInfo);
begin begin
inherited create(); inherited Create();
FTypeInfo:=ATypeInfo; FTypeInfo:=ATypeInfo;
if assigned(FTypeInfo) then if assigned(FTypeInfo) then
FTypeData:=GetTypeData(ATypeInfo); FTypeData:=GetTypeData(ATypeInfo);
@ -2596,6 +2609,18 @@ begin
Result := fMethods; Result := fMethods;
end; end;
function TRttiType.GetMethod(const aName: String): TRttiMethod;
var
methods: specialize TArray<TRttiMethod>;
method: TRttiMethod;
begin
methods := GetMethods;
for method in methods do
if SameText(method.Name, AName) then
Exit(method);
Result := Nil;
end;
function TRttiType.GetDeclaredMethods: specialize TArray<TRttiMethod>; function TRttiType.GetDeclaredMethods: specialize TArray<TRttiMethod>;
begin begin
Result := Nil; Result := Nil;

View File

@ -330,6 +330,7 @@ begin
CheckEquals(AValue.IsClass, False); CheckEquals(AValue.IsClass, False);
CheckEquals(AValue.IsObject, True); CheckEquals(AValue.IsObject, True);
Check(AValue.AsObject=ATestClass); Check(AValue.AsObject=ATestClass);
Check(PPointer(AValue.GetReferenceToRawData)^ = Pointer(ATestClass));
CheckEquals(TTestValueClass(AValue.AsObject).AInteger, 54329); CheckEquals(TTestValueClass(AValue.AsObject).AInteger, 54329);
ATestClass.Free; ATestClass.Free;
end; end;
@ -350,6 +351,7 @@ begin
CheckEquals(value.GetArrayLength, 2); CheckEquals(value.GetArrayLength, 2);
CheckEquals(value.GetArrayElement(0).AsInteger, 42); CheckEquals(value.GetArrayElement(0).AsInteger, 42);
CheckEquals(value.GetArrayElement(1).AsInteger, 21); CheckEquals(value.GetArrayElement(1).AsInteger, 21);
Check(PPointer(value.GetReferenceToRawData)^ = Pointer(arr));
value.SetArrayElement(0, 84); value.SetArrayElement(0, 84);
CheckEquals(arr[0], 84); CheckEquals(arr[0], 84);
end; end;