Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting old Contnrs.TObjectList on Win64 [duplicate]

Tags:

64-bit

delphi

We have some old classes using Contnrs.TObjectList, and in some cases custom compare-functions are used to sort these lists, using something like this:

procedure TMyClass.SortItems;

  function CompareFunction(Item1, Item2: Pointer): Integer;
  begin
    Result := TSomeItem(Item1).Value - TSomeItem(Item2).Value;
  end;

begin
  Sort(@CompareFunction);
end;

This code has worked without issues when compiled for Win32, but when we compile it for Win64, we have found that the sorting doesn't work anymore.

I have fixed some of them by using Generics.Collections.TObjectList<T> instead, and modifying the CompareFunction and how it is called. So my guess is that it has to do with the way the CompareFunction is called, by prefixing it with the @ operator, which as I understand, refers to the address of the function.

Why does the code above doesn't work on Win64, and what would be the proper way to fix it?

like image 514
alondono Avatar asked Nov 23 '17 04:11

alondono


1 Answers

TObjectList.Sort() expects a standalone function for its callback.

An inner function shares the stack frame of its parent function (so it can access the parent's local variables and parameters). So you can't use an inner function as the callback. You got away with it in 32bit, due to a fluke in how functions work in 32bit. But this won't work anymore in 64bit.

You need to move CompareFunction() out on its own, eg:

function CompareFunction(Item1, Item2: Pointer): Integer;
begin
  Result := TSomeItem(Item1).Value - TSomeItem(Item2).Value;
end; 

procedure TMyClass.SortItems;
begin
  Sort(@CompareFunction);
end;

This will work in both 32bit and 64bit.

like image 162
Remy Lebeau Avatar answered Nov 05 '22 04:11

Remy Lebeau