2024-05-14 09:38:14 +02:00
|
|
|
function PSVariantIFCToTValue(aValue: PPSVariantIFC; var aValues: TArray<TValue>): Boolean;
|
|
|
|
var
|
|
|
|
l_len: Integer;
|
|
|
|
i: Integer;
|
|
|
|
arr: TArray<TValue>;
|
|
|
|
arr_varrec: TArray<TVarRec>;
|
|
|
|
|
|
|
|
begin
|
|
|
|
Result := True;
|
|
|
|
case aValue^.aType.BaseType of
|
|
|
|
{$IFNDEF PS_NOWIDESTRING}
|
|
|
|
btWidestring,
|
|
|
|
btUnicodestring,
|
|
|
|
{$ENDIF}
|
|
|
|
btString: aValues := aValues + [TValue.From<String>(pstring(aValue^.dta)^)];
|
|
|
|
btU8, btS8: aValues := aValues + [TValue.From<Byte>(pbyte(aValue^.dta)^)];
|
|
|
|
btU16, BtS16: aValues := aValues + [TValue.From<Word>(pword(aValue^.dta)^)];
|
|
|
|
btU32, btS32: aValues := aValues + [TValue.From<Cardinal>(pCardinal(aValue^.dta)^)];
|
|
|
|
{$IFNDEF PS_NOINT64}bts64:{$ENDIF} aValues := aValues + [TValue.From<Int64>(pint64(aValue^.dta)^)];
|
|
|
|
btSingle: aValues := aValues + [TValue.From<Single>(PSingle(aValue^.dta)^)];
|
|
|
|
btDouble: aValues := aValues + [TValue.From<Double>(PDouble(aValue^.dta)^)];
|
|
|
|
btExtended: aValues := aValues + [TValue.From<Extended>(PExtended(aValue^.dta)^)];
|
|
|
|
btPChar: aValues := aValues + [TValue.From<PChar>(ppchar(aValue^.dta)^)];
|
|
|
|
btChar: aValues := aValues + [TValue.From<Char>(pchar(aValue^.dta)^)];
|
|
|
|
btClass: aValues := aValues + [TValue.From<TObject>(TObject(aValue^.dta^))];
|
|
|
|
btRecord: aValues := aValues + [TValue.From<Pointer>(aValue^.dta)];
|
|
|
|
btStaticArray: aValues := aValues + [TValue.From<Pointer>(aValue^.dta)];
|
|
|
|
btVariant:
|
|
|
|
aValues := aValues + [TValue.From(Variant(aValue^.dta^))];
|
|
|
|
btArray:
|
|
|
|
begin
|
|
|
|
if Copy(aValue^.aType.ExportName, 1, 10) = '!OPENARRAY' then begin
|
|
|
|
l_len := PSDynArrayGetLength(Pointer(aValue^.Dta^), aValue^.aType) - 1;
|
|
|
|
SetLength(arr, 0);
|
|
|
|
for i := 0 to l_len do begin
|
|
|
|
if not PSVariantIFCToTValue(PPSVariantIFC(IPointer(aValue^.Dta^) + IPointer(i) * 3 * SizeOf(Pointer)), arr) then begin
|
|
|
|
Result := False;
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
arr_varrec := TValueArrayToArrayOfConst(arr);
|
|
|
|
//in case of openarray we should provide TWO params: first is pointer to array,
|
|
|
|
aValues := aValues + [TValue.From<Pointer>(@arr_varrec[0])];
|
|
|
|
//2nd - integer with arraylength - 1 (high)
|
|
|
|
aValues := aValues + [TValue.From<Integer>(l_len)];// = High of OpenArray
|
|
|
|
end
|
|
|
|
else //dynarray = just push pointer
|
|
|
|
aValues := aValues + [TValue.From<Pointer>(aValue^.dta)];
|
|
|
|
end;
|
|
|
|
btSet:
|
|
|
|
begin
|
|
|
|
case TPSTypeRec_Set(aValue^.aType).aByteSize of
|
|
|
|
1: aValues := aValues + [TValue.From<Byte>(pbyte(aValue^.dta)^)];
|
|
|
|
2: aValues := aValues + [TValue.From<Word>(pWord(aValue^.dta)^)];
|
|
|
|
3,
|
|
|
|
4: aValues := aValues + [TValue.From<Cardinal>(pCardinal(aValue^.dta)^)];
|
|
|
|
else
|
|
|
|
aValues := aValues + [TValue.From<Pointer>(aValue^.dta)];
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
else
|
|
|
|
Result := False;
|
|
|
|
end; { case }
|
|
|
|
end;
|
|
|
|
|
2023-09-13 12:43:51 +02:00
|
|
|
function TPSExec.InnerfuseCall(_Self, Address: Pointer; CallingConv: TPSCallingConvention; Params: TPSList; res: PPSVariantIFC): Boolean;
|
|
|
|
var SysCalConv : TCallConv;
|
|
|
|
Args: TArray<TValue>;
|
|
|
|
Arg : TValue;
|
|
|
|
i : Integer;
|
|
|
|
fvar: PPSVariantIFC;
|
|
|
|
IsConstr : Boolean;
|
|
|
|
IsStatic : Boolean;
|
|
|
|
ctx: TRTTIContext;
|
|
|
|
RttiType : TRttiType;
|
|
|
|
ResValue : TValue;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
IsStatic := _Self = nil;
|
|
|
|
case CallingConv of
|
|
|
|
cdRegister : SysCalConv := ccReg;
|
|
|
|
cdPascal : SysCalConv := ccPascal;
|
|
|
|
cdCdecl : SysCalConv := ccCdecl;
|
|
|
|
cdStdCall : SysCalConv := ccStdCall;
|
|
|
|
cdSafeCall : SysCalConv := ccSafeCall;
|
|
|
|
else
|
|
|
|
SysCalConv := ccReg;//to prevent warning "W1036 Variable might not have been initialized"
|
|
|
|
end;
|
|
|
|
|
|
|
|
if not IsStatic then begin
|
|
|
|
{$IFDEF CPUX86}
|
|
|
|
if CallingConv <> cdPascal then
|
|
|
|
{$ENDIF CPUX86}
|
|
|
|
Args := Args + [TValue.From<Pointer>( _Self )];
|
|
|
|
end;
|
|
|
|
|
|
|
|
for I := 0 to Params.Count - 1 do
|
|
|
|
begin
|
|
|
|
if Params[i] = nil
|
|
|
|
then Exit;
|
|
|
|
fvar := Params[i];
|
|
|
|
|
|
|
|
if fvar.varparam then
|
|
|
|
begin { var param }
|
|
|
|
case fvar.aType.BaseType of
|
|
|
|
btArray, btVariant, btSet, btStaticArray, btRecord, btInterface, btClass, {$IFNDEF PS_NOWIDESTRING} btWideString, btWideChar, {$ENDIF}
|
|
|
|
btU8, btS8, btU16, btS16, btU32, btS32, btSingle, btDouble, btExtended, btString, btPChar, btChar, btCurrency,
|
|
|
|
btUnicodeString
|
|
|
|
{$IFNDEF PS_NOINT64}, bts64{$ENDIF}:
|
|
|
|
Arg := TValue.From<Pointer>( Pointer(fvar.dta) );
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
end;
|
2024-05-14 09:38:14 +02:00
|
|
|
Args := Args + [Arg];
|
2023-09-13 12:43:51 +02:00
|
|
|
end
|
2024-05-14 09:38:14 +02:00
|
|
|
else begin
|
|
|
|
if not PSVariantIFCToTValue(fvar, Args) then Exit;
|
2023-09-13 12:43:51 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{$IFDEF CPUX86}
|
|
|
|
if not IsStatic then begin
|
|
|
|
if CallingConv = cdPascal then
|
|
|
|
Args := Args + [TValue.From<Pointer>( _Self )];
|
|
|
|
end;
|
|
|
|
{$ENDIF CPUX86}
|
|
|
|
|
|
|
|
IsConstr := (Integer(CallingConv) and 64) <> 0;
|
|
|
|
if not assigned(res) then
|
|
|
|
begin
|
|
|
|
Invoke(Address, Args, SysCalConv, nil); { ignore return }
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
case res.atype.basetype of
|
|
|
|
{ add result types here }
|
|
|
|
btString: tbtstring(res.dta^) := tbtstring(Invoke(Address,Args,SysCalConv,TypeInfo(String),IsStatic).AsString);
|
|
|
|
{$IFNDEF PS_NOWIDESTRING}
|
|
|
|
btUnicodeString: tbtunicodestring(res.dta^) := Invoke(Address,Args,SysCalConv,TypeInfo(String),IsStatic).AsString;
|
|
|
|
btWideString: tbtWideString(res.dta^) := Invoke(Address,Args,SysCalConv,TypeInfo(String),IsStatic).AsString;
|
|
|
|
{$ENDIF}
|
|
|
|
btU8, btS8: pbyte(res.dta)^ := Byte(Invoke(Address,Args,SysCalConv,TypeInfo(Byte),IsStatic).AsInteger);
|
|
|
|
btU16, btS16: pword(res.dta)^ := word(Invoke(Address,Args,SysCalConv,TypeInfo(Word),IsStatic).AsInteger);
|
|
|
|
btU32, btS32: pCardinal(res.dta)^ := Cardinal(Invoke(Address,Args,SysCalConv,TypeInfo(Cardinal),IsStatic).AsInteger);
|
|
|
|
{$IFNDEF PS_NOINT64}bts64:{$ENDIF} pInt64(res.dta)^ := Int64(Invoke(Address,Args,SysCalConv,TypeInfo(Int64),IsStatic).AsInt64);
|
|
|
|
btSingle: psingle(res.dta)^ := Double(Invoke(Address,Args,SysCalConv,TypeInfo(Single),IsStatic).AsExtended);
|
|
|
|
btDouble: pdouble(res.dta)^ := Double(Invoke(Address,Args,SysCalConv,TypeInfo(Double),IsStatic).AsExtended);
|
|
|
|
btExtended: pextended(res.dta)^ := Extended(Invoke(Address,Args,SysCalConv,TypeInfo(Extended),IsStatic).AsExtended);
|
|
|
|
{$IFDEF FPC}
|
|
|
|
btPChar: ppchar(res.dta)^ := pchar(Invoke(Address,Args,SysCalConv,TypeInfo(PChar),IsStatic).AsOrdinal);
|
|
|
|
btChar: pchar(res.dta)^ := Char(Invoke(Address,Args,SysCalConv,TypeInfo(Char),IsStatic).AsChar);
|
|
|
|
{$ELSE}
|
|
|
|
btPChar: ppchar(res.dta)^ := pchar(Invoke(Address,Args,SysCalConv,TypeInfo(PChar),IsStatic).AsType<PChar>());
|
|
|
|
btChar: pchar(res.dta)^ := Char(Invoke(Address,Args,SysCalConv,TypeInfo(Char),IsStatic).AsType<Char>());
|
|
|
|
{$ENDIF}
|
|
|
|
btSet:
|
|
|
|
begin
|
|
|
|
case TPSTypeRec_Set(res.aType).aByteSize of
|
|
|
|
1: byte(res.Dta^) := Byte(Invoke(Address,Args,SysCalConv,TypeInfo(Byte),IsStatic).AsInteger);
|
|
|
|
2: word(res.Dta^) := word(Invoke(Address,Args,SysCalConv,TypeInfo(Word),IsStatic).AsInteger);
|
|
|
|
3,
|
|
|
|
4: Longint(res.Dta^) := Cardinal(Invoke(Address,Args,SysCalConv,TypeInfo(Cardinal),IsStatic).AsInteger);
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
for RttiType in ctx.GetTypes do
|
|
|
|
if (RttiType.Name.ToUpper.EndsWith(String(res.aType.FExportName))) and (RttiType.TypeKind = tkSet)
|
|
|
|
and (RttiType.TypeSize = TPSTypeRec_Set(res.aType).aByteSize) then
|
|
|
|
begin
|
|
|
|
Invoke(Address,Args,SysCalConv,RttiType.Handle,IsStatic).ExtractRawData(res.dta);
|
|
|
|
Break;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
btClass:
|
|
|
|
begin
|
|
|
|
{$IFNDEF FPC}for RttiType in ctx.GetTypes do
|
|
|
|
if (RttiType.Name.ToUpper.EndsWith(String(res.aType.FExportName))) and (RttiType.TypeKind = tkClass) then{$ENDIF}
|
|
|
|
begin
|
|
|
|
TObject(res.dta^) := Invoke(Address,Args,SysCalConv,{$IFDEF FPC}TypeInfo(TObject){$ELSE}RttiType.Handle{$ENDIF},IsStatic, IsConstr).AsObject;
|
|
|
|
{$IFNDEF FPC}Break;{$ENDIF}
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
btStaticArray:
|
|
|
|
begin
|
|
|
|
for RttiType in ctx.GetTypes do
|
|
|
|
if (RttiType.Name.ToUpper.EndsWith(String(res.aType.FExportName))) and (RttiType.TypeKind = tkArray) then
|
|
|
|
begin
|
|
|
|
CopyArrayContents(res.dta, Invoke(Address,Args,SysCalConv,RttiType.Handle,IsStatic).GetReferenceToRawData, TPSTypeRec_StaticArray(res.aType).Size, TPSTypeRec_StaticArray(res.aType).ArrayType);
|
|
|
|
Break;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
btRecord:
|
|
|
|
begin
|
|
|
|
for RttiType in ctx.GetTypes do
|
|
|
|
if (RttiType.Name.ToUpper.EndsWith(String(res.aType.FExportName))) and (RttiType.TypeKind = tkRecord) then
|
|
|
|
begin
|
|
|
|
CopyArrayContents(res.dta, (Invoke(Address,Args,SysCalConv,RttiType.Handle,IsStatic).GetReferenceToRawData), 1, res.aType);
|
|
|
|
Break;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
btArray: //need to check with open arrays
|
|
|
|
begin
|
|
|
|
for RttiType in ctx.GetTypes do
|
|
|
|
if (RttiType.Name.ToUpper.EndsWith(String(res.aType.FExportName))) and (RttiType.TypeKind = tkDynArray) then
|
|
|
|
begin
|
|
|
|
ResValue := Invoke(Address,Args,SysCalConv,RttiType.Handle,IsStatic);
|
|
|
|
if ResValue.GetArrayLength > 0 then
|
|
|
|
CopyArrayContents(res.dta, ResValue.GetReferenceToRawData, 1, res.aType)
|
|
|
|
else
|
|
|
|
res.dta := nil;
|
|
|
|
Break;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
btVariant:
|
|
|
|
begin
|
|
|
|
PVariant(res.dta)^ := Invoke(Address, Args, SysCalConv, TypeInfo(Variant), IsStatic).AsVariant;
|
|
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
else
|
|
|
|
// writeln(stderr, 'Result type not implemented!');
|
|
|
|
Exit;
|
|
|
|
end; { case }
|
|
|
|
end; //assigned(res)
|
|
|
|
|
|
|
|
Result := True;
|
|
|
|
end;
|