简体   繁体   English

动态与静态DLL链接是不同的

[英]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. 我有一个C DLL,并希望从Delphi XE3 Update 2中调用它。奇怪的是,在我的项目中,动态调用它与静态调用它是不同的。 Here is the 'minimal' code to reproduce (I have changed the Lib/functionnames): 这是重现的'最小'代码(我更改了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: 查看生成的汇编程序代码,我意识到变量'keylist'被放入eax寄存器:

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 但后来dll(我不知道这是哪个功能,一些入口点或密钥列表例程)

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. 似乎eax中的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. 但由于参数现在没有存储在eax中,因此覆盖eax并不重要。

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 . 运行时链接变量使用stdcall和加载时间链接变量使用register

Make the calling conventions match and all will be well. 使呼叫约定匹配,一切都会好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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