簡體   English   中英

動態與靜態DLL鏈接是不同的

[英]Dynamic vs. Static DLL Linking is different

我有一個C DLL,並希望從Delphi XE3 Update 2中調用它。奇怪的是,在我的項目中,動態調用它與靜態調用它是不同的。 這是重現的'最小'代碼(我更改了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.

輸出是

static: keylist is nil

這意味着動態調用函數與靜態不同。 確實通過動態調用來正確初始化密鑰列表。 查看生成的匯編程序代碼,我意識到變量'keylist'被放入eax寄存器:

testProject.dpr.34: keylist_open(@keylist);
004D16A2 B804B04D00       mov eax,$004db004
004D16A7 E8ECC6FFFF       call keylist_open

然后

testProject.dpr.12: function keylist_open (keylist: PPointer): Integer; external 'libLib';
004CDD98 FF255CC54D00     jmp dword ptr [$004dc55c]

又一次跳

libLib.keylist_open:
5B364508 E903A23D00       jmp $5b73e710

但后來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
...

似乎eax中的eax參數被覆蓋了。 兩行之后,動態調用的代碼是:

testProject.dpr.37: keylist_openDynamic(@keylist);

004D16CE 6804B04D00       push $004db004
004D16D3 FF15F0564D00     call dword ptr [$004d56f0]

跳到

libLib.keylist_open:
5B364508 E903A23D00       jmp $5b73e710

因此對於相同的代碼。 但由於參數現在沒有存儲在eax中,因此覆蓋eax並不重要。

打電話給任何人在這里揭曉,出了什么問題,即我的靜態代碼有什么問題?為什么?

這兩個版本的調用約定不同。 運行時鏈接變量使用stdcall和加載時間鏈接變量使用register

使呼叫約定匹配,一切都會好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM