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