I have a C DLL and want to call it from Delphi XE3 Update 2. Curiously it seems that in my project calling it dynamically IS different to calling it statically. Here is the 'minimal' code to reproduce (I have changed the Lib/functionnames):
program testProject;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, System.classes, Windows;
function keylist_open (keylist: PPointer): Integer; external 'libLib';
var
Handle: HINST;
DLLName: PChar = 'libLib.dll';
type
Tkeylist_open = function(keylist: PPointer): Integer; stdcall;
const
keylist_openDynamic: Tkeylist_open = nil;
var
keylist: Pointer;
begin
Handle := LoadLibrary(DLLName);
if Handle = 0 then
Exit;
@keylist_openDynamic := GetProcAddress(Handle, 'keylist_open');
keylist_open(@keylist);
if (keylist = nil) then
Writeln('static: keylist is nil');
keylist_openDynamic(@keylist);
if (keylist = nil) then
Writeln('dynamic: keylist is nil');
end.
The output is
static: keylist is nil
Which means that calling the function dynamically is different from statically. the keylist indeed gets initialized correctly by calling it dynamically. looking into the generated assembler code i realize that the variable 'keylist' is put into the eax register:
testProject.dpr.34: keylist_open(@keylist);
004D16A2 B804B04D00 mov eax,$004db004
004D16A7 E8ECC6FFFF call keylist_open
then
testProject.dpr.12: function keylist_open (keylist: PPointer): Integer; external 'libLib';
004CDD98 FF255CC54D00 jmp dword ptr [$004dc55c]
and another jump
libLib.keylist_open:
5B364508 E903A23D00 jmp $5b73e710
but then the dll (i do not know which function this is, some entry point or the keylist routine) there is
5B73E710 55 push ebp
5B73E711 8BEC mov ebp,esp
5B73E713 81ECDC000000 sub esp,$000000dc
5B73E719 53 push ebx
5B73E71A 56 push esi
5B73E71B 57 push edi
5B73E71C 8DBD24FFFFFF lea edi,[ebp-$000000dc]
5B73E722 B937000000 mov ecx,$00000037
5B73E727 B8CCCCCCCC mov eax,$cccccccc
...
it seems that the eax parameter is being overwritten in eax. two lines later the code for the dynamic call is:
testProject.dpr.37: keylist_openDynamic(@keylist);
004D16CE 6804B04D00 push $004db004
004D16D3 FF15F0564D00 call dword ptr [$004d56f0]
jumping to
libLib.keylist_open:
5B364508 E903A23D00 jmp $5b73e710
and thus to the very same code. But as the parameter is now not stored in eax, overwriting eax does not matter.
call anyone shed a light here, what is going wrong, ie what is wrong with my static code and why?
The two versions differ in the calling convention. The run time linking variant uses stdcall
and the load time linking variant uses register
.
Make the calling conventions match and all will be well.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.