Delphi RTTI. Что хранится в tkPointer? Как с помощью RTTI получить значение в p: PInteger;?

Не могу понять, как в RTTI получить значение переменной если она указана как ссылка tkPointer? Т.е есть:

 type
  TRec = record
    i: Integer;
    p: PInteger;
  end;

Как с помощью RTTI получить значение в p: PInteger;, не ссылку а число p^.

Я конечно могу вот так, но это только для PInteger а нужно для всех ссылок что не являются Pointer и PPointer.

    ValuePointer := TValue(V).AsType<Pointer>;
    if ValuePointer <> nil then    
      Value := PInteger(ValuePointer)^;

Пишу парсер классов и record вот покажу часть кода:

procedure TAmToJsonVariableRtti.AddJsonValue(P:PParam;F:TJsonDataValueHelper;V :TValue; LastType:TRttiType);
var Dym:TRttiDynamicArrayType;
i,Count:integer;
VA :TValue;
rttiContext : TRttiContext;
s,AName:string;
RTyp:TRttiType;
  enumBuffer: set of Byte;
  enumType: PTypeInfo;
  enumData: PTypeData;
  enumDenLimiter:boolean;
begin
{ TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat,
  tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString,
  tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray, tkUString,
  tkClassRef, tkPointer, tkProcedure, tkMRecord);}



     case V.Kind of
         tkInterface    : begin
                           if  V.AsInterface is tOBJECT then
                            begin

                              if P.Level>P.MaxLevel then
                              begin
                                 F.Value:='[break:MaxLevel:tkInterface]';
                                 exit;
                              end;
                              inc(P.Level);
                              try
                                 if P.NeedNameType then
                                 AName:='Object:'+ TObject(V.AsInterface).ClassName
                                 else
                                 AName:= 'Object';
                                 RTyp:= rttiContext.GetType(TObject(V.AsInterface).ClassInfo);
                                 ParsJsonValue(P,F.ObjectValue[AName].ObjectValue,TObject(V.AsInterface),RTyp);
                              finally
                               dec(P.Level);
                              end;


                             // F.Value:=  TObject(V.AsInterface).ClassName;
                            end;

                          end;
        tkInteger       : F.IntValue:=       V.AsInteger;
        tkPointer       : begin
                           F.IntValue:=   V.AsInteger;
                           F.Value:=      '$'+ IntToHex(Integer(V.AsType<Pointer>));
                          end;

        tkEnumeration   : begin

                           F.Value:=  GetEnumName(V.TypeInfo, V.AsOrdinal);

                          end;
        tkFloat         : begin

                              if V.TypeInfo = TypeInfo(TDateTime) then
                              F.DateTimeValue:=  V.AsExtended
                              else
                              F.FloatValue:=    V.AsExtended;


                          end;
        tkSet           : begin
                              V.ExtractRawData(@enumBuffer);

                              if V.TypeInfo=nil then  exit;
                              if V.TypeInfo.TypeData=nil then  exit;
                              if V.TypeInfo.TypeData.CompType=nil then  exit;

                              enumType := V.TypeInfo.TypeData.CompType^;



                              if enumType=nil then  exit;

                              enumData := enumType.TypeData;
                              if enumData=nil then  exit;
                              s:=V.TypeInfo.Name+':[';
                              enumDenLimiter:=false;
                              for i := enumData.MinValue to enumData.MaxValue do
                              if i in enumBuffer then
                              begin
                               if enumDenLimiter then
                               s:= s+', ';
                               s:= s+ GetEnumName(enumType, i);
                               enumDenLimiter:=true;
                              end;
                              s:= s+']';
                              F.Value:=  s;


                          end;
        tkVariant       :  F.VariantValue:=  V.AsVariant;
        tkInt64         :  F.LongValue:=     V.AsInt64;

        tkChar,
        tkWChar,
        tkLString,
        tkWString,
        tkUString,
        tkString       :   F.Value:=         V.AsString;


        tkMRecord,
         tkRecord :      begin
                              if P.Level>P.MaxLevel then
                              begin
                                 F.Value:='[break:MaxLevel:tkRecord]';
                                 exit;
                              end;
                           inc(P.Level);
                           ParsJsonValue(P, F.ObjectValue,V.GetReferenceToRawData,LastType);
                           dec(P.Level);
                         end;


        tkClass :        begin
                              if P.Level>P.MaxLevel then
                              begin
                                 F.Value:='[break:MaxLevel:tkClass]';
                                 exit;
                              end;
                           inc(P.Level);
                           ParsJsonValue(P, F.ObjectValue,V.AsObject,LastType);
                           dec(P.Level);
                         end;

        tkDynArray,
        tkArray        : begin
                            if P.Level>P.MaxLevel then
                            begin
                                F.Value:='[break:MaxLevel:tkArray]';
                               exit;
                            end;
                            Count:= V.GetArrayLength;
                            F.ArrayValue.Count:=Count;
                             for I := 0 to Count-1 do
                             begin
                                 VA:=V.GetArrayElement(i);
                                // s:=VA.TypeInfo.Name;

                                 RTyp:= rttiContext.GetType(VA.TypeInfo);
                                 if  (RTyp<> nil) then
                                 begin
                                 inc(P.Level);
                                 AddJsonValue(P,F.ArrayValue[i],VA,RTyp);
                                 dec(P.Level);
                                 end;

                             end;
                         end;
     end;


end;

в строке

        tkPointer       : begin
                           F.IntValue:=   V.AsInteger;
                           F.Value:=      '$'+ IntToHex(Integer(V.AsType<Pointer>));
                          end;

я могу только значение адреса а как сам тип данным получить что бы его пропарсить?

на выходе я вижу а хочу что бы pinteger имел значение числа

проблема еше в том что тот модуль где этот код будет не может знать всех возможных типов например я не могу там написать

if  V is PInteger then else if V is PBoolean then.....

т.к это будет работать только для PInteger и PBoolean нужно как то для всех возможных ссылок код придумать

УРА! нашел решение

        tkPointer       : begin

                             Ps:= V.AsType<Pointer>;
                             if (V.TypeInfo <> typeinfo(Pointer)) and (V.TypeInfo <> typeinfo(PPointer)) then
                             begin
                                 enumType := V.TypeInfo.TypeData.RefType^;
                                 RTyp:= rttiContext.GetType(enumType);
                                 AName:= 'Type:'+enumType.Name;
                                 if Ps<>Pointer($FFFFFFFF) then
                                 begin
                                     try
                                       TValue.Make(
                                         Ps,
                                        enumType,
                                        VA);
                                     except
                                       Ps:=nil;
                                     end;
                                 end
                                 else
                                 begin

                                 end;

                             end
                             else
                             begin
                                Ps:=nil;
                             end;
                             F.ObjectValue['Addr'].Value:= '$'+ IntToHex(Integer(V.AsType<Pointer>));

                                 try
                                 if (Ps <> nil) and (Ps<>Pointer($FFFFFFFF)) and (RTyp<>nil) then
                                 AddJsonValue(P,F.ObjectValue[AName],VA,RTyp);
                                 except
                                   Ps:=nil;
                                 end;
                           //ParsJsonValue(P,F.ObjectValue[AName].ObjectValue,TObject(V.AsInterface),RTyp);

                         // F.IntValue:=   VA.AsInteger;
                          // F.Value:=      '$'+ IntToHex(Integer(V.AsType<Pointer>));
                          end;

Вот


Ответы (0 шт):