windows - 动态与静态 DLL 链接不同

标签 windows delphi dll linker delphi-xe3

我有一个 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

这意味着动态调用函数不同于静态调用函数。 key 列表确实通过动态调用得到了正确的初始化。 查看生成的汇编代码,我意识到变量“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

使调用约定匹配,一切都会好起来的。

关于windows - 动态与静态 DLL 链接不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18677203/

相关文章:

delphi - Lazarus 中是否有类似于 Delphi "Use debug DCUs"的选项

c++ - 一个像素一个像素的 3d 图形程序 [通过拖动窗口更快地绘图]

windows - dokan sshfs 有多稳定?

delphi - 在 **if 语句** 中使用 **and** 运算符

c++ - Qt 创建的应用程序在没有 Qt creator 的情况下无法运行

c++ - 当调用dll函数时,参数对象的成员变量的内存地址发生变化

c# - C sharp "public IntPtr pHandle = IntPtr.Zero;"相当于 Delphi "hp: Pointer"

linux - 程序员应该使用什么工具从 Windows 机器在 Ubuntu 机器上工作

windows - Turbo Studio 虚拟化

delphi - 更换功能单元