Delphi几种调用模式的区别

几种调用模式的区别?
作者:Builder_Soft

请高手帮我说一下几种调用模式的区别?  
http://www.faq-it.org/office/">faq-it.org/office/ ---------------------------------------------------------------  
 
register    Delphi默认调用        从左到右  
cdecl          c/c++  默认调用        从右到左  
stdcall      API,DLL默认调用      从右到左  
safecall    OLE默认调用              从右到左  
---------------------------------------------------------------  
 
五种调用模式:register、cdecl、pascal、stdcall和safecall。根据调用模式的不同,参数可以通过CPU的寄存器或堆栈传递给函数和过程。register模式使用CPU的三个寄存器传递参数,而其它模式则用堆栈来传递参数。在register和pascal模式下从左至右传递参数,即参数表中最左边的参数最先被求值并传递,而最右边的参数最后求值并传递。另三种模式cdecl、stdcall和safecall则从右至左传递参数。这些模式中除了cdecl外,都是由过程和函数在返回时清除堆栈中的参数,而对于cdecl模式,需由调用者在调用结束时清除堆栈中的参数。  
  如何选择调用模式,有以下三条规则:  
  1.Delphi  使用register模式作为缺省调用模式以提高运行效率。  
  2.如果有调用关系的几个模块是用不同语言编写的,其接口应使用stdcall模式。  
3.如果要实现双界面函数和过程,应使用safecall模式。  
 
 
不如去看书  
---------------------------------------------------------------  
 
这里的指示字就是在声明函数或过程时附加在例程标题之后的保留字,默认为register,即是  唯一使用  CPU寄存器的参数传递方式,也是传递速度最快的方式;  
 
pascal:  调用协议仅用于向后兼容,即向旧的版本兼容;    
cdecl:  多用于  C和  C++语言编写的例程,也用于需要由调用者清除参数的例程;    
stdcall:  和safecall主要用于调用Windows  API  函数;其中safecall还用于双重接口。  
---------------------------------------------------------------  
 
在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(' rel="nofollow"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为数据段)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值