[英]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.