I've been writing a little test harness to test C and C++ dlls. It's for 
this btw.
http://cplus.about.com/od/programmingchallenges/a/onchallenge1.htm

The Test harness for the C and C++ dlls was written in Delphi 5. It works ok 
except it kept crashing quite badly when I called a function which passed 
the address of a record in so the called function can access the record 
data. I verified that the record structure size was identical in Delphi and 
the dll.

The call worked fine, but when the delphi function which encapsulates the 
call to the dll function exited, it bombed out. Ie I had done naughty things 
to the stack. The calling convention was stdcall in the Delphi app, the 
default (winapi in Microsoft parlance) in the C/C++ dll which equates to 
stdcall on Windows XP.

I was doing this using loadlibrary btw. Ie select a dll, then use 
GetProcAddress and call it.

type
TPlayerHistory = packed record // 104 bytes in size- same as in dll
  MoveCount : integer;
  Moves     : array[1..100] of char;
end;
TmyfuncMove = function(var p : TPlayerHistory):integer;stdcall;

var
dllhandle : THandle;
pdllpathname : pchar;
dllpathname:string;
s : string;
fm : TMyFuncMove;
p : Pchar;
history : TPlayerHistory;
This is the function that bombs out.

function GetMove:string;
var b : byte;  // <- fixes the bug, crashes if this unused variable is 
removed!
begin
  result :='Failed to locate entry point GetMove';
  try
    fm := GetProcAddress(dllhandle,'GetMove');
  except
    fm := nil;
  end;
  if not assigned(fm)then
    exit
  else
     begin
       try
          result := Inttostr(fm(History));  // <- Calls the function here
       except
         on e:exception do
           begin
             ShowMessage(E.Message);
           end;
         end;
     end;
end;  // <- crashes here

It's called like this

procedure TForm1.btnStartClick(Sender: TObject);
var i : integer;
begin
  dllhandle := 0;
  try
    pdllpathname := pchar(dllpathname);
    dllhandle := LoadLibrary(pdllpathname);
    fillchar(history.moves,sizeof(history.moves),' ');
    for i:= 1 to 10 do
      begin
        History.MoveCount := i-1;
        if i >1 then
          History.Moves[i-1] := 'R';
        ListBox1.Items.Add('Move '+ Inttostr(i)+' = '+ GetMove);
      end;
  finally
    FreeLibrary( dllhandle );
  end;
end;

I solved it and I think it is a bug in Delphi 5. If there is no local 
variable declared in GetMove, I don't think it saves the stack correctly (I 
had optimise turned off btw) and so crashes. It also crashes if optimization 
is turned on, I presume because it zaps the local variable as it is unused.

At first I thought it was a calling convention mismatch but I proved that it 
wasn't, by adding two dummy parameters and checking that it could still 
access the History record in the dll.

So am I right that it is a bug or missing something else?

David Bolton

_________________________________________________________________
The next generation of Hotmail is here!  http://www.newhotmail.co.uk

Reply via email to