gpt4 book ai didi

delphi - 方法的默认通用比较器返回不正确的结果

转载 作者:行者123 更新时间:2023-12-03 15:07:14 24 4
gpt4 key购买 nike

在使用建议的multicast delegate响应 Signals and slots implementation in Delphi 的方法问题,代码无法添加多个事件处理程序。

该问题与向TDelegateImpl<T>.Add()中的事件列表添加方法有关。 ,TList<T>.IndexOf方法使用 Compare 方法来查找现有方法,结果始终为 0 - 意味着 TMethod 的 Left 和 Right 相同。 Equals 方法使用 TMethod类型转换并显式比较 TMethod.CodeTMethod.Data ,其中Compare转换为始终相同的地址。

为什么是Compare用于TList<T>.IndexOf而不是Equals

最佳答案

问题是这个函数:

function Compare_Method(Inst: PSimpleInstance; const Left, Right: TMethodPointer): Integer;
begin
if PInt64(@Left)^ < PInt64(@Right)^ then
Result := -1
else if PInt64(@Left)^ > PInt64(@Right)^ then
Result := 1
else
Result := 0;
end;

这将方法与 Int64 进行比较。这不起作用,因为 @ 在这里可能没有效果。

CPU View 证实了这一点:

System.Generics.Defaults.pas.1089: begin
00447690 55 push ebp
00447691 8BEC mov ebp,esp
System.Generics.Defaults.pas.1090: if PInt64(@Left)^ < PInt64(@Right)^ then
00447693 8B4510 mov eax,[ebp+$10]
00447696 8B5004 mov edx,[eax+$04]
00447699 8B00 mov eax,[eax]
0044769B 8B4D08 mov ecx,[ebp+$08]
0044769E 3B5104 cmp edx,[ecx+$04]
004476A1 7506 jnz $004476a9
004476A3 3B01 cmp eax,[ecx]
004476A5 7309 jnb $004476b0
004476A7 EB02 jmp $004476ab
004476A9 7D05 jnl $004476b0
System.Generics.Defaults.pas.1091: Result := -1
004476AB 83C8FF or eax,-$01
004476AE EB21 jmp $004476d1
System.Generics.Defaults.pas.1092: else if PInt64(@Left)^ > PInt64(@Right)^ then
004476B0 8B4510 mov eax,[ebp+$10]
etc...

要将两个 TMethod 作为 Int64 进行比较,应该是:

System.Generics.Defaults.pas.1090: if PInt64(@Left)^ < PInt64(@Right)^ then
00447693 8B4510 lea eax,[ebp+$10] // not MOV
00447696 8B5004 mov edx,[eax+$04]
00447699 8B00 mov eax,[eax]
0044769B 8B4D08 lea ecx,[ebp+$08] // not MOV
0044769E 3B5104 cmp edx,[ecx+$04]
004476A1 7506 jnz $004476a9
004476A3 3B01 cmp eax,[ecx]
etc...

这清楚地表明 PInt64(@Left)^ 被解释为 PInt64(Left)^

对于 Delphi 32 和 Delphi 64 来说,正确的实现应该或多或少看起来像这样:

function Compare_Method(Inst: PSimpleInstance; const Left, Right: TMethodPointer): Integer;
var
LCode, LData: PByte;
RCode, RData: PByte;
begin
LCode := PByte(TMethod(Left).Code);
LData := PByte(TMethod(Left).Data);
RCode := PByte(TMethod(Right).Code);
RData := PByte(TMethod(Right).Data);
if LData < RData then
Result := -1
else if LData > RData then
Result := 1
else if LCode < RCode then
Result := -1
else if LCode > RCode then
Result := 1
else
Result := 0;
end;

关于delphi - 方法的默认通用比较器返回不正确的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7428244/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com