它适用于 32 位平台,但不适用于 64 位平台 这是例子
TVerbInfo = packed record
Verb: Smallint;
Flags: Word;
end;
var
VerbInfo: TVerbInfo;
strList : TStringList;
verb : Smallint;
flags : Word;
begin
strList := TStringList.create();
.....
verbInfo.verb := verb;
verbInfo.flags := flags;
strList.addObject('verb1',TObject(VerbInfo)); //invalid typecast happened here
end;
有人可以帮助我吗?非常感谢你
你可以尝试这样的事情:
function MakeVerbInfoObject(const AVerbInfo: TVerbInfo): TObject;
begin
Result := nil;
Move(AVerbInfo, Result, SizeOf(AVerbInfo));
end;
strList.addObject('verb1', MakeVerbInfoObject(VerbInfo));
您的演员表
TObject(VerbInfo)
将编译,前提是SizeOf(TObject) = SizeOf(TVerbInfo)
。但 TObject
是一个指针,因此它的大小因架构而异。另一方面,SizeOf(TVerbInfo)
不随架构而变化。因此,演员只能在一种架构上工作。
使用像这样的强制转换就是在前泛型 Delphi 中必须做的事情。但现在,您应该使用通用容器。
例如,如果您有一个列表并且字符串是唯一的,那么您可以使用字典:
TDictionary<string, TVerbInfo>
如果可能存在重复的字符串,那么您将需要一个新的记录声明:
type
TVerbInfo = record
Name: string
Verb: Integer;
Flags: Word;
end;
然后将这些列表存储在
TList<TVerbInfo>
最后一点是您应该避免使用打包记录。这些会导致数据结构不对齐,进而导致性能不佳。
我认为你必须在不同的平台上运行它并比较结果
ShowMessage( IntToStr( SizeOf( Integer ) ) );
ShowMessage( IntToStr( SizeOf( Pointer ) ) );
ShowMessage( IntToStr( SizeOf( TVerbInfo ) ) );
ShowMessage( IntToStr( SizeOf( TObject ) ) );
我怀疑你不能进行硬铸,因为尺寸不同。
您可以尝试使用类似的解决方法
type TBoth = record
case byte of
0: ( rec: TVerbInfo);
1: ( obj: TObject);
end;
您也可以尝试使用
TDictionary<String, TVerbInfo>
类型代替 TStringList
我昨晚尝试了 Uli 的代码,但它不起作用,因为 MakeVerbInfoObject 不会为您提供指向记录的有效指针。
type
PVerbInfo= ^TVerbInfo;
TVerbInfo = packed record
Verb: Smallint;
Flags: Word;
end;
function MakeVerbInfoObject(const AVerbInfo: TVerbInfo): TObject;
begin
Result := nil;
Move(AVerbInfo, Result, SizeOf(AVerbInfo));
end;
procedure Test;
var
VerbInfo: TVerbInfo;
List: TObjectList;
begin
VerbInfo.Verb:= 7;
VerbInfo.Flags:= 8;
List:= TObjectList.Create(false);
List.Add(MakeVerbInfoObject(VerbInfo));
// AV here!!!!!!!!
var i:= PVerbInfo(List[0])^.Verb;
FreeAndNil(List);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Test2;
end;
但是,这可以工作(在 32/64 位上测试):
Type
PVerbInfo2= ^TVerbInfo2;
TVerbInfo2= packed record
Verb: SmallInt;
Flags: Word;
end;
procedure Test;
var
VerbInfo: TVerbInfo2;
Obj: TObject;
List: TObjectList;
P: PVerbInfo2;
begin
VerbInfo.Flags:= 7;
VerbInfo.Verb:= 8;
List:= TObjectList.Create(false);
//List.add(Pointer(VerbInfo)); // "E2089 Invalid typecast" when compiling on 64 bit
List.Add(TObject(@VerbInfo));
// This gives correct values:
var i := PVerbInfo2(List[0])^.Verb;
FreeAndNil(List);
end;