简体   繁体   中英

Dynamic vs. Static DLL Linking is different

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM