Search code examples
delphidelphi-2010parameter-passingcreatethread

Passing a parameter to CreateThread


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?


Solution

  • 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;
    

    enter image description here


    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?