我必须做一些记录子数据大小计算,所以创建类似
的东西function GetSubDataSize(const Rec: TRecord): integer;
begin
Result:=integer(@Rec.Field2) - integer(@Rec.Field1);
end;
一切都没问题,除了一种情况,如果Field之一是一个过程或函数指针,那么在
的情况下TRecord = record
Field2: procedure(Sender: TObject) of object;
end;
该函数获取过程本身的地址。有没有办法对字段进行类型转换以获取字段的地址而不是函数的地址?我知道我可以使用变体部分记录来解决它,但只是不想使用它。
谢谢,
最高
答案 0 :(得分:11)
你试过@@?
type
TRecord = record
Field1:integer;
Field2:TNotifyEvent;
end;
function GetSubDataSize(const Rec: TRecord): integer;
begin
result := integer(@@Rec.Field2) - integer(@Rec.Field1);
end;
给了我8,这是我对Delphi 2010的期望。
N - [
答案 1 :(得分:3)
由于Field2是方法指针,您应该使用它:
此代码
type
RRecord = record
Field1: Integer;
Field2: procedure (Sender: TObject) of object;
Field3: Integer;
end;
var
rec: RRecord;
begin
Memo1.Lines.Add(Format('@rec.Field1 %d', [Integer(@rec.Field1)]));
Memo1.Lines.Add(Format('@rec.Field2 %d', [Integer(@rec.Field2)]));
Memo1.Lines.Add(Format('@TMethod(rec.Field2).Code %d', [Integer(@TMethod(rec.Field2).Code)]));
Memo1.Lines.Add(Format('@TMethod(rec.Field2).Data %d', [Integer(@TMethod(rec.Field2).Data)]));
Memo1.Lines.Add(Format('@rec.Field3 %d', [Integer(@rec.Field3)]));
end;
在表单的OnCreate上添加备忘录,生成:
@rec.Field1 1244820
@rec.Field2 4052
@TMethod(rec.Field2).Code 1244828
@TMethod(rec.Field2).Data 1244832
@rec.Field3 1244836
第二行显示随机值,因为没有为本地记录变量分配任何内容。第三行和第四行显示了TMethod成员的地址。
请注意,由于方法似乎总是8字节对齐,因此可能(可能)填写记录。 (至少在D2009 / D2010中)。
答案 2 :(得分:1)
不幸的是,似乎没有任何简单的方法可以按照您的方式执行此操作。变体部分记录可能会起作用,但我同意,这有点难看。
但如果您使用的是Delphi 2010,则有更好的方法。看起来你正试图遍历记录的所有字段并确定它们的偏移量。这可以通过扩展RTTI来完成,如下所示:
procedure test;
var
ctx: TRttiContext;
recType: TRttiType;
recField: TRttiField;
begin
ctx := TRttiContext.Create;
recType := ctx.GetType(TypeInfo(TMyRec));
for recField in recType.GetFields do
writeln(format('Field %s is at offset %d.', [recField.Name, recField.Offset]));
end;
(这篇文章假定你是在一个纯粹出于演示目的编写的控制台应用程序中,就像我写的那样测试它。随意修改它以满足你的需求......)