Reputation: 189
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?
Upvotes: 3
Views: 7853
Reputation: 11
And don't use Pointer
cast in:
handle := CreateThread(nil, 0, @ThreadProc, **Pointer**(b), 0, tID);
b
is already a Pointer
(a Class
, which is an Object
Pointer
)
Upvotes: 1
Reputation: 613461
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?
Upvotes: 10
Reputation: 54832
You're forgetting the stdcall
directive.
function ThreadProc(param: Pointer) : DWORD; stdcall;
Upvotes: 9