I am having a problem passing a class reference as the parameter to the ThreadProc in a call to CreateThread. Here is a sample program that demonstrates the problem I am having:
program test;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows, Dialogs;
type
TBlah = class
public
fe: Integer;
end;
function ThreadProc(param: Pointer) : DWORD;
begin
ShowMessage(IntToStr(TBlah(param).fe));
Result := 0;
end;
var
tID: DWORD;
handle: THandle;
b: TBlah;
begin
b := TBlah.Create;
b.fe := 54;
handle := CreateThread(nil, 0, @ThreadProc, Pointer(b), 0, tID);
WaitForSingleObject(handle, INFINITE);
end.
The call to ShowMessage
pops up a message box that has something like 245729105
in it, not 54
like I expect.
This is probably just a basic misunderstanding of how Delphi works, so could someone please tell me how to get this working properly?
The problem here is that your thread function has the wrong calling convention. You need to declare it with the stdcall
convention:
function ThreadProc(param: Pointer) : DWORD; stdcall;
Having said that, it would be more idiomatic to just use a TThread
descendant which handles the OOP to C function back to OOP transitioning for you. That would look like this:
type
TBlah = class(TThread)
protected
procedure Execute; override;
public
fe: Integer;
end;
procedure TBlah.Execute;
begin
ShowMessage(IntToStr(fe));
end;
var
b: TBlah;
begin
b := TBlah.Create(True);
b.fe := 42;
b.Start;
b.WaitFor;
end.
Incidentally, does anyone know why Windows.pas declares TFNThreadStartRoutine
as TFarProc
rather than a proper typed function pointer?