请高手帮我说一下几种调用模式的区别?

解决方案 »

  1.   

    register  Delphi默认调用    从左到右
    cdecl     c/c++ 默认调用    从右到左
    stdcall   API,DLL默认调用   从右到左
    safecall  OLE默认调用       从右到左
      

  2.   

    五种调用模式:register、cdecl、pascal、stdcall和safecall。根据调用模式的不同,参数可以通过CPU的寄存器或堆栈传递给函数和过程。register模式使用CPU的三个寄存器传递参数,而其它模式则用堆栈来传递参数。在register和pascal模式下从左至右传递参数,即参数表中最左边的参数最先被求值并传递,而最右边的参数最后求值并传递。另三种模式cdecl、stdcall和safecall则从右至左传递参数。这些模式中除了cdecl外,都是由过程和函数在返回时清除堆栈中的参数,而对于cdecl模式,需由调用者在调用结束时清除堆栈中的参数。
      如何选择调用模式,有以下三条规则:
      1.Delphi 使用register模式作为缺省调用模式以提高运行效率。
      2.如果有调用关系的几个模块是用不同语言编写的,其接口应使用stdcall模式。
    3.如果要实现双界面函数和过程,应使用safecall模式。
    不如去看书
      

  3.   

    这里的指示字就是在声明函数或过程时附加在例程标题之后的保留字,默认为register,即是 唯一使用 CPU寄存器的参数传递方式,也是传递速度最快的方式;pascal: 调用协议仅用于向后兼容,即向旧的版本兼容; 
    cdecl: 多用于 C和 C++语言编写的例程,也用于需要由调用者清除参数的例程; 
    stdcall: 和safecall主要用于调用Windows API 函数;其中safecall还用于双重接口。
      

  4.   

    在DELPHI中,有两种方法可用于调用一个储存在DLL(动态链接库)中的过程。 一、 调用方法 1、 静态调用或显式装载使用一个外部声明子句,使DLL在应用程序开始执行前即被装入。例如: Function instring (sourcestr: Pchar ;
    check: char): integer; far; external ‘ demostr’
    这种方式要在单元的interface 部分用external 指示字列出要从DLL中调用的例程。Far 指令表明可以被其他段,例如其他单元调用的子例程。所有在单元接口中声明的子例程在缺省情况下都是Far类型的,其相反的指令是near。 如果external 后什么也不跟,必须用 {$ L } 编译指令预先指定一个DLL名字,如: { $ L Mydlls.dll }
    Procedure setstring(var str: string) ;
    stdcall ; external
    但是使用静态调用方法时,程序无法在运行时间里决定DLL的调用。在DELPHI中使用DLL时,例程的标识符必须与DLL中相应输出例程的标识符完全一致(尽管DELPHI本身大小写不敏感)。 2、 动态调用或隐式装入 使用WINDOWS API 函数 Loadlibrary 和GetprocAddress可以实现在运行时间里的动态装载DLL,并调用其中的过程。 例如:       Type TMyProc=Procedure (Param:Pchar ) ;Stdcall;
          Var MyProc: TMyproc;
           MyHandle:THandle;
           MyHandle:=LoadLibrary (‘Mydll’) ;
           If MyHandle<  =0 then
            Raise Exception.Create
            ( ‘动态链接库调用失败,错误代码
            是:’+Inttostr(Getlasterror))
            else 
             @MyProc:=GetProcAddress(MyHandle,’demoproc’);
           if not Assigned(MyProc) then
            Raise Exception.Create('GetProcAddress 
            调用失败,错误代码
               是:’+inttostr(getlasterror))
            else MyProc(Pchar(‘a string’));
            Freelibrary(Myhandle); // 卸载DLL
    二、 调用方式 1、 通过过程、函数名; 2、 通过过程、函数别名; 3、 通过过程、函数的顺序号 例: Function Getstring : string ; stdcall ; external ‘Mydlls.dll’ name ‘Mygetstr’name  子句指定函数名Getstring 改为Mygetstr,当程序调用这个例程时,使用Mygetstr这个名字; Function Getstring : string ; stdcall ; external ‘Mydlls.dll’ index 5 Index  子句通过索引号引入例程可以减少DLL的加载时间。 三、 调用约定 调用约定,是指调用例程时参数的传递顺序。DELPHI中DLL支持的调用约定有: 调用约定 参数传递顺序
    Register 从左到右
    Pascal 从左到右
    Stdcall 从右到左
    Cdecl 从右到左
    Safecall 从右到左
    使用Stdcall 方式,能保证不同语言写的DLL的兼容性,同时它也是WINDOWS API的约定方式;Delphi 3。0、4。0的默认调用方式为Register ;Cdecl是采用 C/C++的调用约定,适用于DLL是由C++语言编写的;Safecall 是适合于声明OLE对象中的方法。 四、 DLL中的变量和段 一个DLL声明的任何变量都为自己私有 ,调用它的模块不能直接使用它定义的变量。要使用时必须通过过程或函数界面才能完成,对DLL来说,它永远都没有机会使用调用它的模块中的声明的变量。一个DLL没有自己的SS(堆栈段),它使用调用它的应用程序的堆栈。因此在DLL中的过程、函数不要假定DS=SS(DS为数据段)。