mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-22 16:49:23 +02:00
+ add TMethodImplementation class
git-svn-id: trunk@40698 -
This commit is contained in:
parent
9a23613b9d
commit
f97688a07b
@ -16,6 +16,7 @@ unit Rtti experimental;
|
|||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
{$modeswitch advancedrecords}
|
{$modeswitch advancedrecords}
|
||||||
|
{$Assertions on}
|
||||||
|
|
||||||
{ Note: since the Lazarus IDE is not yet capable of correctly handling generic
|
{ Note: since the Lazarus IDE is not yet capable of correctly handling generic
|
||||||
functions it is best to define a InLazIDE define inside the IDE that disables
|
functions it is best to define a InLazIDE define inside the IDE that disables
|
||||||
@ -314,6 +315,31 @@ type
|
|||||||
function ToString: String; override;
|
function ToString: String; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TMethodImplementationCallbackMethod = procedure(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue) of object;
|
||||||
|
TMethodImplementationCallbackProc = procedure(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue);
|
||||||
|
|
||||||
|
TMethodImplementation = class
|
||||||
|
private
|
||||||
|
fLowLevelCallback: TFunctionCallCallback;
|
||||||
|
fCallbackProc: TMethodImplementationCallbackProc;
|
||||||
|
fCallbackMethod: TMethodImplementationCallbackMethod;
|
||||||
|
fArgs: specialize TArray<TFunctionCallParameterInfo>;
|
||||||
|
fArgLen: SizeInt;
|
||||||
|
fRefArgs: specialize TArray<SizeInt>;
|
||||||
|
fFlags: TFunctionCallFlags;
|
||||||
|
fResult: PTypeInfo;
|
||||||
|
fCC: TCallConv;
|
||||||
|
function GetCodeAddress: CodePointer;
|
||||||
|
procedure InitArgs;
|
||||||
|
procedure HandleCallback(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
|
||||||
|
constructor Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod);
|
||||||
|
constructor Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackProc);
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
destructor Destroy; override;
|
||||||
|
property CodeAddress: CodePointer read GetCodeAddress;
|
||||||
|
end;
|
||||||
|
|
||||||
TRttiInvokableType = class(TRttiType)
|
TRttiInvokableType = class(TRttiType)
|
||||||
protected
|
protected
|
||||||
function GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>; virtual; abstract;
|
function GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>; virtual; abstract;
|
||||||
@ -656,6 +682,10 @@ resourcestring
|
|||||||
SErrInvokeRttiDataError = 'The RTTI data is inconsistent for method: %s';
|
SErrInvokeRttiDataError = 'The RTTI data is inconsistent for method: %s';
|
||||||
SErrInvokeCallableNotProc = 'The callable value is not a procedure variable for: %s';
|
SErrInvokeCallableNotProc = 'The callable value is not a procedure variable for: %s';
|
||||||
SErrInvokeCallableNotMethod = 'The callable value is not a method variable for: %s';
|
SErrInvokeCallableNotMethod = 'The callable value is not a method variable for: %s';
|
||||||
|
SErrMethodImplNoCallback = 'No callback specified for method implementation';
|
||||||
|
SErrMethodImplInsufficientRtti = 'Insufficient RTTI to create method implementation';
|
||||||
|
SErrMethodImplCreateFailed = 'Failed to create method implementation';
|
||||||
|
SErrMethodImplCreateNoArg = 'TMethodImplementation can not be created this way';
|
||||||
|
|
||||||
var
|
var
|
||||||
PoolRefCount : integer;
|
PoolRefCount : integer;
|
||||||
@ -2405,6 +2435,116 @@ begin
|
|||||||
Result := FString;
|
Result := FString;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TMethodImplementation }
|
||||||
|
|
||||||
|
function TMethodImplementation.GetCodeAddress: CodePointer;
|
||||||
|
begin
|
||||||
|
Result := fLowLevelCallback.CodeAddress;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMethodImplementation.InitArgs;
|
||||||
|
var
|
||||||
|
i, refargs: SizeInt;
|
||||||
|
begin
|
||||||
|
i := 0;
|
||||||
|
refargs := 0;
|
||||||
|
SetLength(fRefArgs, Length(fArgs));
|
||||||
|
while i < Length(fArgs) do begin
|
||||||
|
if (fArgs[i].ParamFlags * [pfVar, pfOut] <> []) and not (pfHidden in fArgs[i].ParamFlags) then begin
|
||||||
|
fRefArgs[refargs] := fArgLen;
|
||||||
|
Inc(refargs);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if pfArray in fArgs[i].ParamFlags then begin
|
||||||
|
Inc(i);
|
||||||
|
if (i = Length(fArgs)) or not (pfHigh in fArgs[i].ParamFlags) then
|
||||||
|
raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
|
||||||
|
Inc(fArgLen);
|
||||||
|
end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then
|
||||||
|
Inc(fArgLen)
|
||||||
|
else if (pfResult in fArgs[i].ParamFlags) then
|
||||||
|
fResult := fArgs[i].ParamType;
|
||||||
|
|
||||||
|
Inc(i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
SetLength(fRefArgs, refargs);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMethodImplementation.HandleCallback(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
|
||||||
|
var
|
||||||
|
i, argidx: SizeInt;
|
||||||
|
args: TValueArray;
|
||||||
|
res: TValue;
|
||||||
|
begin
|
||||||
|
Assert(fArgLen = Length(aArgs), 'Length of arguments does not match');
|
||||||
|
SetLength(args, fArgLen);
|
||||||
|
argidx := 0;
|
||||||
|
i := 0;
|
||||||
|
while i < Length(fArgs) do begin
|
||||||
|
if pfArray in fArgs[i].ParamFlags then begin
|
||||||
|
Inc(i);
|
||||||
|
Assert((i < Length(fArgs)) and (pfHigh in fArgs[i].ParamFlags), 'Expected high parameter after open array parameter');
|
||||||
|
TValue.MakeOpenArray(aArgs[i - 1], SizeInt(aArgs[i]), fArgs[i].ParamType, args[argidx]);
|
||||||
|
end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then begin
|
||||||
|
TValue.Make(aArgs[i], fArgs[i].ParamType, args[argidx]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Inc(i);
|
||||||
|
Inc(argidx);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Assigned(fCallbackMethod) then
|
||||||
|
fCallbackMethod(aContext, args, res)
|
||||||
|
else
|
||||||
|
fCallbackProc(aContext, args, res);
|
||||||
|
|
||||||
|
{ copy back var/out parameters }
|
||||||
|
for i := 0 to High(fRefArgs) do begin
|
||||||
|
args[fRefArgs[i]].ExtractRawData(aArgs[fRefArgs[i]]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Assigned(fResult) then
|
||||||
|
res.ExtractRawData(aResult);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod);
|
||||||
|
begin
|
||||||
|
fCC := aCC;
|
||||||
|
fArgs := aArgs;
|
||||||
|
fResult := aResult;
|
||||||
|
fFlags := aFlags;
|
||||||
|
fCallbackMethod := aCallback;
|
||||||
|
InitArgs;
|
||||||
|
fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
|
||||||
|
if not Assigned(fLowLevelCallback) then
|
||||||
|
raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackProc);
|
||||||
|
begin
|
||||||
|
fCC := aCC;
|
||||||
|
fArgs := aArgs;
|
||||||
|
fResult := aResult;
|
||||||
|
fFlags := aFlags;
|
||||||
|
fCallbackProc := aCallback;
|
||||||
|
InitArgs;
|
||||||
|
fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
|
||||||
|
if not Assigned(fLowLevelCallback) then
|
||||||
|
raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TMethodImplementation.Create;
|
||||||
|
begin
|
||||||
|
raise EInvalidOpException.Create(SErrMethodImplCreateNoArg);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TMethodImplementation.Destroy;
|
||||||
|
begin
|
||||||
|
fLowLevelCallback.Free;
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TRttiMethod }
|
{ TRttiMethod }
|
||||||
|
|
||||||
function TRttiMethod.GetHasExtendedInfo: Boolean;
|
function TRttiMethod.GetHasExtendedInfo: Boolean;
|
||||||
|
Loading…
Reference in New Issue
Block a user