delphi调用DLL中的函数,函数类型要一样吗?请大家看看,该如何解决

delphi调用DLL中的函数,函数类型要一样吗?请大家看看
情况如下:
用delphi做一DLL,里面有一输出函数;定义如下:
function   GetMax:   integer;   stdcall;
实现代码:
function   GetMax:   Integer;
begin
    Result   :=   100;
end;
工程文件:
library   Project1;

uses
    SysUtils,
    Classes,
    Unit1   in   'Unit1.pas '   {Form1};

exports
    GetMax;

{$R   *.res}

begin
end.

调用DLL的代码如下:
procedure   button1OnClick(sender:   TObject);
var
    a:   function(b:   PChar;   c:   boolean):   Integer;     //   此函数类型与DLL中定义的函数参数个数不一样,但调用没有问题,不知道是什么原因?
    max:   integer;
    LibHandle:   THandle;
begin
    LibHandle   :=   LoadLibrary( 'DLL路径 ');     //   成功
    try
        if   LibHandle   <>   0   then
        begin
            @a   :=   GetProcAddress(LibHandle,   'GetMax ');   //   取函数地址
            max   :=   a( ' ',true);   //   成功,取得100,为什么,DLL中定义的方法是没有参数的啊?
        end;
    finally
        FreeLibrary(LibHandle);
    end;
end;

请各位高手帮忙解释下,小弟搞不懂是什么原因,为什么只要函数名称和DLL中定义的函数名称相同,参数不一样都可以调用啊。

------解决方案--------------------
实际上,对于函数GetMax来说,你只是使用了它的一个入口地址而已。并且DLL定义的函数GetMax,其调用约定是stdcall,而你在实际调用时,却没有遵守这个约定,而是使用了Delphi默认的register约定。所以,参数仍旧按register方式传进了函数a。我把你的函数和调用过程改了一下,你看一下:

//DLL函数:
function GetMax : integer; stdcall; export;
//下面的句子, 是把EAX、EDX、ECX三个寄存器的值相加,并赋值给Result
//register调用约定下,函数参数(三个以内),优先使用上述三个寄存器传递
//因为你只是使用了GetMax的入口地址,所以上面的stdcall约定无效
asm
ADD EAX, EDX
ADD EAX, ECX
end;

//调用
procedure TForm1.Button1Click(Sender: TObject);
var
a: function(var1,var2,var3 : integer): Integer;//注意此处,默认是register方式
max: integer;
LibHandle: THandle;
begin
LibHandle := LoadLibrary( 'Test.dll ');
try
if LibHandle <> 0 then
begin
@a := GetProcAddress(LibHandle, 'GetMax ');
max := a(4, 2, 3); //三个参数
Showmessage(inttostr(max)); // 9
end;
finally
FreeLibrary(LibHandle);
end;
end;

如果在函数a声明时,改为:

a: function(var1,var2,var3 : integer): Integer; stdcall;

则会出错。
------解决方案--------------------
无论什么编程语言,最终都是会翻译成机器语言执行,因为机器只能读懂机器语言
在机器语言这个级别:函数、过程、类、类型、事件、方法等等都不存在
只有机器指令和操作数

a( ' ', true);
被翻译成机器指令大概是:
mov eax,$00xx0000
mov dl,$01
call a

就是向寄存器填写参数
在dll中的函数也没有访问这两寄存器(eax、dl)所以相安无事
如果参数多余3个,则第四个参数器会做入栈操作,如果dll函数没有出栈操作这会导致异常

var
a: function(a, b, c, d: Integer): Integer; //可以这样测试

通过IDE的CPU查看器可以看到执行的指令
能执行通只能说是纯属巧合而已