• Delphi调用规则(Calling conventions)


    声明一个过程或函数时候可以指定一种调用规则,可使用如下关键字:register,pascal,cdecl,stdcall,safecall,比如:

    function MyFunction(X, Y: Real): Real; cdecl;

    ...

    调用规则决定了参数传递给程序的顺序,同时也影响参数从堆栈和参数使用的寄存器中释放,错误和意外的处理。DELPHI中缺省的调用规则为register.

    • register和pascal:参数从左至右传递;也就是说最左边的参数最先计算和传递,最右边的参数最晚计算和传递。cdecl,stdcall,safecall:参数从右至左传递。

    • 除了cdecl之外的调用规则,过程或函数在返回前从堆栈中释放参数。cdecl规则则是由调用者在过程或函数返回后释放。

    • register规则使用3个CPU寄存器传递参数,而其他调用规则中传递的参数是入栈的。

    • safecall规则实现了对意外的防火墙。在WINDOWS,这个实现了COM进程间的错误通知。

    请看表格:

    由此可见,缺省的register规则是最高效的,因为它通常避免了创建一个栈结构。cdecl在调用CC++写的动态链接库时是有用的,但是推荐stdcallsafecall,通常cdecl用于调用其他代码写的链接库。在Windows上,操作系统APIstdcallsafecall规则。其他操作系统基本上使用cdecl

    safecall规则用于双接口(dual-interface)方法,pascal规则是为了向后兼容。

    调用规则简介

    Register

    Delphi默认的调用规则,效率非常高,但规则很复杂,下面是它的简要规则:

    1.头三个不大于4个字节(DWORD)的参数从左到右的传入EAX,EDX,ECX寄存器;接下去的参数按从左到右压栈。

    2.浮点数总压栈,不管它所占的字节是多少。

    3.对象方法总是有一个Self隐含参数,这个参数在所有的参数前面,即总是传给EAX。

    4.栈现场必须由函数自己清理。

    Stdcall

    Windows API的标准调用规则,效率不高,但规则很简单:

    1.参数总是从右向左地压栈。

    2.栈现场必须由函数自己清理。

    Cdecl

    这是C语言的标准调用规则,在Delphi中很少需要用到这种规则,但Delphi仍然提供了支持。

    1.与stdcall类似,参数总是从右向左地压栈。

    2.栈现场必须由调用者清理。

    Safecall

    Safecall常用于COM,Delphi作了很多处理,使得函数返回值小于0时,自动抛出异常。

    1.任何Safecall函数,都可以转换成等价的Stdcall函数。

    2.函数返回时,Delphi自动检查其返回值,如果小于0,就引发reSafeCallError异常。

    代码示例

    调用dll wz_buildtab.dll

    调用方法 procedure wz_cjdmk(aFlag:Integer=0); stdcall; //厂家代码库

    procedure TFrmwzgg.BitBtnsccjClick(Sender: TObject);  
    
    var
    
        h: THandle;  
    
        p: procedure(aFlag: Integer);stdcall;  
    
    begin
    
        h := LoadLibrary(pchar('wz_buildtab.dll'));  
    
        if h <> 0 then
    
        begin
    
            @p := GetProcAddress(h, 'wz_cjdmk');  
    
            if @p <> nil then
    
            begin
    
                p(1);  
    
            end;  
    
        end;  
    
    end;
    

    附:

    Delphi帮助文档(英文版)

    When you declare a procedure or function, you can specify a calling convention using one of the directives register, pascal, cdecl, stdcall, and safecall. For example,

    function MyFunction(X, Y: Real): Real; cdecl;

     ...

    Calling conventions determine the order in which parameters are passed to the routine. They also affect the removal of parameters from the stack, the use of registers for passing parameters, and error and exception handling. The default calling convention is register.

    The register and pascal conventions pass parameters from left to right; that is, the leftmost parameter is evaluated and passed first and the rightmost parameter is evaluated and passed last. The cdecl, stdcall, and safecall conventions pass parameters from right to left.

    For all conventions except cdecl, the procedure or function removes parameters from the stack upon returning. With the cdecl convention, the caller removes parameters from the stack when the call returns.

    The register convention uses up to three CPU registers to pass parameters, while the other conventions pass all parameters on the stack.

    The safecall convention implements exception "firewall".On Windows, this implements interprocess COM error notification.

    The table below summarizes calling conventions.

    Directive        Parameter order        Clean-up        Passes parameters in registers?

    register        Left-to-right          Routine        Yes

    pascal           Left-to-right          Routine        No

    cdecl             Right-to-left          Caller          No

    stdcall        Right-to-left          Routine        No

    safecall        Right-to-left          Routine        No

    The default register convention is the most efficient, since it usually avoids creation of a stack frame. (Access methods for published properties must use register.) The cdecl convention is useful when you call functions from shared libraries written in C or C++, while stdcall and safecall are recommended, in general, for calls to external code. On Windows, the operating system APIs are stdcall and safecall. Other operating systems generally use cdecl. (Note that 

    stdcall is more efficient than cdecl.)

    The safecall convention must be used for declaring dual-interface methods. The pascal convention is maintained for backward compatibility. For more information on calling conventions, see Program control.

    The directives near, far, and export refer to calling conventions in 16-bit Windows programming. They have no effect in 32-bit applications and are maintained for backward compatibility only.

  • 相关阅读:
    自己设计的SSO登录流程图
    Java泛型:泛型类、泛型接口和泛型方法
    Java中泛型的各种使用
    Java总结篇系列:Java泛型
    java生成MD5校验码
    Android SQLite数据库之事务的学习
    Android SQLite详解
    android删除表和清空表
    Android 软键盘自动弹出和关闭
    java中表示二进制、八进制、十进制、十六进制
  • 原文地址:https://www.cnblogs.com/liuke1987/p/2916171.html
Copyright © 2020-2023  润新知