我有一个在Delphi 6中工作的函数。现在我尝试将旧项目迁移到Delphi XE8,但是这个函数不能正常工作。
请帮帮我。
旧功能:
function ReadString(var P: Pointer): String;
var
B: Byte;
begin
B := Byte(P^);
SetLength(Result, B);
P := Pointer( Integer(P) + 1);
Move(P^, Result[1], Integer(B));
P := Pointer( Integer(P) + B );
end;
我尝试将其更改为取消编码,但它不起作用:
function ReadString(var P: Pointer): String;
var
B: Byte;
LResult: AnsiString;
begin
B := Byte(P^);
SetLength(LResult, B);
P := Pointer( Integer(P) + 1);
Move(P^, LResult[1], Integer(B));
P := Pointer( Integer(P) + B );
Result := String(LResult);
end
该功能用于:
GetIntfMetaData(Myobj as IFController,IntfMD,True);
procedure GetIntfMetaData(Info: PTypeInfo; var IntfMD: TIntfMetaData; MethodArrayOpt: TFillMethodArrayOpt);
var
I, Offset: Integer;
Methods: Integer;
BaseRTTIMethods: Integer;
HasRTTI: Integer;
PP: PPTypeInfo;
P: Pointer;
SelfMethCount: Integer;
IntfMethod: PIntfMethEntry;
begin
P := Pointer(Info);
IntfMD.Info := Info;
{ tkKind }
ReadByte(P);
IntfMD.Name := ReadString(P);
{ Interface flags }
ReadByte(P);
IntfMD.UnitName := ReadString(P);
Methods := ReadWord(P); { # methods }
HasRTTI := ReadWord(P); { $FFFF if no RTTI, # methods again if has RTTI }
if HasRTTI = $FFFF then
raise EInterfaceRTTIException.CreateFmt(SNoRTTI, [IntfMD.UnitName + '.' + IntfMd.Name]);
{ Save my method count }
SelfMethCount := Methods;
Offset := 0;
{ Size array and fill in information }
SetLength(IntfMD.MDA, Methods);
FillMethodArray(P, @IntfMD, Offset, SelfMethCount);
end;
procedure FillMethodArray(P: Pointer; IntfMD: PIntfMetaData; Offset, Methods: Integer);
var
S: Ansistring;
I, J, K, L: Integer;
ParamCount: Integer;
Kind, Flags: Byte;
ParamInfo: PTypeInfo;
ParamName: Ansistring;
IntfMethod: PIntfMethEntry;
IntfParam: PIntfParamEntry;
begin
for I := 0 to Methods -1 do
begin
IntfMethod := @IntfMD.MDA[Offset];
IntfMethod.Name := ReadString(P);
Kind := ReadByte(P); { tkKind }
IntfMethod.CC := CCMap[ReadByte(P)];
ParamCount := ReadByte(P); { Param count including self }
IntfMethod.ParamCount := ParamCount - 1;
IntfMethod.Pos := Offset;
IntfMethod.HasRTTI := True;
SetLength(IntfMethod.Params, ParamCount);
K := 0;
for J := 0 to ParamCount - 1 do
begin
Flags := ReadByte(P); { Flags }
ParamName := ReadString(P); { Param name }
S := ReadString(P); { Param type name }
L := ReadLong(P); { Param Type Info }
if L <> 0 then
ParamInfo := PPTypeInfo(L)^
else
raise EInterfaceRTTIException.CreateFmt(SNoRTTIParam, [ParamName, IntfMethod.Name, IntfMD.UnitName + '.' + IntfMd.Name]);
if J = 0 then
IntfMethod.SelfInfo := ParamInfo
else
begin
IntfParam := @IntfMethod.Params[K];
IntfParam.Flags := TParamFlags(Flags);
IntfParam.Name := ParamName;
IntfParam.Info := ParamInfo;
Inc(K);
end;
end;
if Kind = Byte(mkFunction) then
begin
S := ReadString(P);
IntfMethod.ResultInfo := PPTypeInfo(ReadLong(P))^;
end;
Inc(Offset);
end;
end;
function ReadByte(var P: Pointer): Byte;
begin
Result := Byte(P^);
P := Pointer( Integer(P) + 1);
end;
答案 0 :(得分:3)
如果您希望通过PTypeInfo结构输入类型名称:
function GetName(p: Pointer): String;
begin
Result := PTypeInfo(P)^.Name;
end;
或者更好地完全限定指针:
function GetName(p: PTypeInfo): String;
begin
Result := P^.Name;
end;
或使用内置功能: TypInfo.GetTypeName
大卫在评论中指出,TTypeInfo
记录以枚举Kind
开头。接下来是Name
字符串。此字段的偏移最好留给编译器计算。
在更新的问题中,很明显在调用函数获取名称之前,使用1(ReadByte)递增指针。不要这样做。 这样做:
IntfMD.Name := GetTypeName(Info);
现在,使用这些知识来处理TTypeInfo
的方法,这也需要更新。
答案 1 :(得分:0)
这是我在互联网上找到的解决方案,但它有效(但我不知道它是否合适):</ p>
chat.on