在 Win64 上对旧 Contnrs.TObjectList 进行排序
Sorting old Contnrs.TObjectList on Win64
我们有一些旧的 类 使用 Contnrs.TObjectList
,在某些情况下,自定义比较函数用于对这些列表进行排序,使用如下:
procedure TMyClass.SortItems;
function CompareFunction(Item1, Item2: Pointer): Integer;
begin
Result := TSomeItem(Item1).Value - TSomeItem(Item2).Value;
end;
begin
Sort(@CompareFunction);
end;
此代码在为 Win32 编译时没有问题,但是当我们为 Win64 编译时,我们发现排序不再起作用。
我已通过使用 Generics.Collections.TObjectList<T>
并修改 CompareFunction
及其调用方式来修复其中一些问题。所以我的猜测是它与 CompareFunction
的调用方式有关,通过在它前面加上 @
运算符作为前缀,据我所知,它指的是函数的地址。
为什么上面的代码在 Win64 上不起作用,修复它的正确方法是什么?
TObjectList.Sort()
需要一个独立的回调函数。
内部函数共享其父函数的栈帧(因此它可以访问父函数的局部变量和参数)。所以你不能使用内部函数作为回调。由于函数在 32 位中的工作方式存在侥幸,您在 32 位中逃脱了。但这在 64 位中不再有效。
您需要自行将CompareFunction()
移出,例如:
function CompareFunction(Item1, Item2: Pointer): Integer;
begin
Result := TSomeItem(Item1).Value - TSomeItem(Item2).Value;
end;
procedure TMyClass.SortItems;
begin
Sort(@CompareFunction);
end;
这将适用于 32 位和 64 位。
我们有一些旧的 类 使用 Contnrs.TObjectList
,在某些情况下,自定义比较函数用于对这些列表进行排序,使用如下:
procedure TMyClass.SortItems;
function CompareFunction(Item1, Item2: Pointer): Integer;
begin
Result := TSomeItem(Item1).Value - TSomeItem(Item2).Value;
end;
begin
Sort(@CompareFunction);
end;
此代码在为 Win32 编译时没有问题,但是当我们为 Win64 编译时,我们发现排序不再起作用。
我已通过使用 Generics.Collections.TObjectList<T>
并修改 CompareFunction
及其调用方式来修复其中一些问题。所以我的猜测是它与 CompareFunction
的调用方式有关,通过在它前面加上 @
运算符作为前缀,据我所知,它指的是函数的地址。
为什么上面的代码在 Win64 上不起作用,修复它的正确方法是什么?
TObjectList.Sort()
需要一个独立的回调函数。
内部函数共享其父函数的栈帧(因此它可以访问父函数的局部变量和参数)。所以你不能使用内部函数作为回调。由于函数在 32 位中的工作方式存在侥幸,您在 32 位中逃脱了。但这在 64 位中不再有效。
您需要自行将CompareFunction()
移出,例如:
function CompareFunction(Item1, Item2: Pointer): Integer;
begin
Result := TSomeItem(Item1).Value - TSomeItem(Item2).Value;
end;
procedure TMyClass.SortItems;
begin
Sort(@CompareFunction);
end;
这将适用于 32 位和 64 位。